Spring中AOP配置环绕通知
AccountServiceImpl.java(service业务层)
package cn.gpxxg.service.Impl;
import cn.gpxxg.service.AccountService;
public class AccountServiceImpl implements AccountService {
public void save() {
System.out.println("保存用户");
}
public void edit(Integer id) {
System.out.println("修改用户" + id * 2);
}
public int del(Integer id) {
System.out.println("删除用户");
return 0;
}
}
bean.xml(此文章中最重要的就是看它)
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="accountService" class="cn.gpxxg.service.Impl.AccountServiceImpl"></bean>
<!--配置loger通知类-->
<bean id="loger" class="cn.gpxxg.utils.Loger"></bean>
<!--配置aop-->
<aop:config>
<!--
aop:pointcut用于配置公共的切面表达式
id:用于执行唯一的id名称
expression:切面表达式的内容
注意:
1、此标签写在aop:aspect标签内部时,只有当前切面使用
2、写在aop:aspect上方时,所有切面都可使用
3、不可写在aop:aspect下方,因为当前xml的约束不允许
-->
<aop:pointcut id="p1" expression="execution(* cn.gpxxg.service.Impl.*.*(..))"></aop:pointcut>
<!--配置切面使用aop:aspect标签-->
<aop:aspect id="logAdvice" ref="loger">
<!--环绕通知-->
<aop:around method="aroundPrintLog" pointcut-ref="p1"></aop:around>
</aop:aspect>
</aop:config>
</beans>
Loger.java(通知类)
package cn.gpxxg.utils;
import org.aspectj.lang.ProceedingJoinPoint;
public class Loger {
/**
* 前置通知
*/
public void beforePrintLog()
{
System.out.println("前置通知-记录日志执行!");
}
/**
* 后置通知
*/
public void afterReturningPrintLog()
{
System.out.println("后置通知-记录日志执行!");
}
/**
* 异常通知
*/
public void afterthrowingPrintLog()
{
System.out.println("异常通知-记录日志执行!");
}
/**
* 最终通知
*/
public void afterPrintLog()
{
System.out.println("最终通知-记录日志执行!");
}
/**
* 环绕通知
* 问题:当我们配置了环绕通知后,切入点方法没有执行,而环绕通知方法执行了
* 分析:通过对比动态代理代码发现,动态代理的环绕通知中有明确的切入点方法调用,而我们的代码中没有
* 解决:Spring为我们提供了一个接口,ProceedingJoinPoint,该接口有一个方法,此方法就明确调用切入点方法。
* 该接口可以作为环绕通知的方法参数,在程序执行时,spring会为我们提供该接口的实现类供我们使用
* 总结:
* spring的环绕通知,就相当与spring为我们提供了一种可以在代码中手动控制增强方法何时执行的方式
*/
public void aroundPrintLog(ProceedingJoinPoint pjp)
{
Object returnValue = null;
try {
// 获取方法执行传递过来的参数,并且增强方法
Object[] args = pjp.getArgs();
Integer id = (Integer) args[0] * 2;
// 前置通知
this.beforePrintLog();
// 执行切入点方法
returnValue = pjp.proceed(args);
// 后置通知
this.afterReturningPrintLog();
} catch (Throwable throwable) {
// 异常通知
this.afterthrowingPrintLog();
throwable.printStackTrace();
} finally {
// 最终通知
this.afterPrintLog();
}
}
}
LogerTest.java(测试类)
package cn.gpxxg;
import cn.gpxxg.service.AccountService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class LogerTest {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
AccountService accountService = ac.getBean("accountService", AccountService.class);
accountService.edit(4);
}
}
还没有评论,来说两句吧...