版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/NameGGG/article/details/78035025
1. Spring AOP 术语
2. 使用Spring AOP
2.1 java 方式
第一步: 使用 @EnableAspectJAutoProxy 注解 启用AspectJ注解的自动代理
@Configurable
@EnableAspectJAutoProxy //启用 AspectJ自动代理
@ComponentScan
public class ConcerConfig {
@Bean //声明Audience bean
public Audience audience(){
return new Audience();
}
}
第二步: 使用@AspectJ 注解 定义一个切面。表明Audience不仅仅是一个POJO,还是一个切面。Audience类中的方法都使用注 解来定义切面的具体行为。
@Aspect
@Component
public class Audience {
...略...
}
第三步: 使用@Pointcut 注解 定义一个切点。切点语法详解
@Aspect
@Component
public class Audience {
/**
* 定义命名的切点
*/
@Pointcut("execution(* springActualCombat.aop.annotationMode.Performance.perform(..))")
public void performance(){}
...略...
}
第四步: 定义通知
1.Spring使用 使用 AspectJ注解来声明通知方法:
注解 | 通知 |
---|---|
@After | 通知方法会在目标方法返回或抛出异常后调用 |
@AfterReturning | 通知方法会在目标方法返回后调用 |
@AfterThrowing | 通知方法会在目标方法抛出异常后调用 |
@Around | 通知方法会将目标方法封装起来 |
@Before | 通知方法会在目标方法调用之前执行 |
@Aspect
@Component
public class Audience {
/**
* 定义命名的切点
*/
@Pointcut("execution(* springActualCombat.aop.annotationMode.Performance.perform(..))")
public void performance(){}
/**
* 开场前
*/
@Before("performance()")
public void silenceCellPhons(){
System.out.println("开场前,关掉手机!");
}
/**
* 开始表演前
*/
@Before("performance()")
public void takeSeats(){
System.out.println("开始表演,鼓掌!");
}
/**
* 结束表演后
*/
@AfterReturning("performance()")
public void applause(){
System.out.println("结束表演,鼓掌!");
}
/**
* 表演失败时
*/
@AfterThrowing("performance()")
public void demandRefund(){
System.out.println("傻逼,退票!");
}
/**----------------------------------------环绕通知-------------------------------------------*/
/**
* 环绕通知的切点
*/
@Pointcut("execution(* springActualCombat.aop.annotationMode.Performance.performSurround(..))")
public void performanceSurround(){}
/**
* 环绕通知
*/
@Around("performanceSurround()")
public void watchPerformance(ProceedingJoinPoint jp){
try {
System.out.println("开始表演,鼓掌!");
jp.proceed(); //必须调用
System.out.println("结束表演,鼓掌!");
} catch (Throwable e) {
System.out.println("傻逼,退票!");
}
}
/**----------------------------------------带参数的通知--------------------------------------- */
Integer singCounts=0;
@Pointcut("execution(* springActualCombat.aop.annotationMode.Performance.singingCount(int))"+" && args(singCount)")
public void singCount(int singCount){};
@Before("singCount(singCount)")
public void performanceCount(int singCount){
singCounts +=singCount;
if (singCounts ==10) {
System.out.println("已演唱"+singCounts+"首!");
}
}
}
2.2 xml 方式
1. 启用AOP
2. Spring AOP的 XML标签
AOP 配置元素 | 用途 |
---|---|
< aop:config> | AOP配置元素 |
< aop:declare-parents> | 以透明的方式为被通知的对象引入额外的接口 |
< aop:aspectj-autoproxy> | 启用@AspectJ注解驱动的切面 |
< aop:aspect> | 定义一个切面 |
< aop:pointcut> | 定义一个切点 |
< aop:advisor> | 定义AOP通知器 |
< aop:after> | 定义AOP后置通知(不管被通知的方法是否执行成功) |
< aop:after-returning> | 定义AOP返回通知 |
< aop:after-throwing> | 定义AOP异常通知 |
< aop:around> | 定义AOP环绕通知 |
< aop:before> | 定义一个AOP前置通知 |
3.XML配置方式:
<bean id="performanceImp" class="springActualCombat.aop.xmlMode.PerformanceImp" />
<bean id="andience" class="springActualCombat.aop.xmlMode.Audience" />
<aop:config>
<!-- 引用audience Bean -->
<aop:aspect ref="andience">
<!-- 定义切点 -->
<aop:pointcut id="performance" expression="execution(* springActualCombat.aop.xmlMode.Performance.perform(..))" />
<!-- 前置通知 -->
<aop:before pointcut-ref="performance" method="silenceCellPhons"/>
<!-- 前置通知 -->
<aop:before pointcut-ref="performance" method="takeSeats"/>
<!-- 后置通知 -->
<aop:after pointcut-ref="performance" method="applause"/>
<!-- 异常时 -->
<aop:after-throwing pointcut-ref="performance" method="demandRefund"/>
<!-- 环绕通知的切点 -->
<aop:pointcut id="performanceSurround" expression="execution(* springActualCombat.aop.xmlMode.Performance.performSurround(..))"/>
<!-- 声明环绕通知 -->
<aop:around pointcut-ref="performanceSurround" method="watchPerformance"/>
<!-- 带参数的通知 -->
<aop:pointcut id="singCount" expression="execution(* springActualCombat.aop.xmlMode.Performance.singingCount(int)) and args(singCount)" />
<aop:before pointcut-ref="singCount" method="performanceCount"/>
</aop:aspect>
</aop:config>
3. 总结
不管你是使用JavaConfig还是XML,Aspect J自动代理都会为使用@Aspect注解的bean 创建一个代理,这个代理会围绕着所有该切面的切点所匹配的bean 。在这种情况下,将会为Concertbean 创建一个代理,Audience类中的通知方法将会在perform()调用前后执行。