一、基本使用
- pom引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>
- 定义切面
//定义切面
@Component
@Aspect
public class testAspect {
//定义切点
@Pointcut("execution(* test.*.*(..))")
public void testPointCut(){}
//指定通知以及通知的范围
@Before("testPointCut()")
public void beforeMethod(){
System.out.println("前置通知。。。");
}
@Around("testPointCut()")
public Object aroundMethod(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("环绕通知上。。。");
Object obj=pjp.proceed();
System.out.println("环绕通知下。。。");
return obj;
}
@After("testPointCut()")
public void afterMethod(){
System.out.println("后置通知。。。");
}
}
- 启动类上增加@EnableAspectJAutoProxy
@SpringBootApplication
@EnableAspectJAutoProxy
public class ZhenChannelApplication {
public static void main(String[] args) {
SpringApplication.run(ZhenChannelApplication.class, args);
}
}
二、实现步骤
- 获取bean
spring是bean的容器,要想拦截(代理)某个bean,要先获取bean,spring定义了bean的生命周期事件,开发者可以拦截这些事件从而获取到所有bean。 - 过滤bean,验证bean是不是需要被代理
aop中切点定义要拦截的bean方法,所以用切点表达式可以验证bean需不需要被拦截 - 将@Before等注解生成拦截方法对象,待后面调用目标方法时调用
三、每一步是如何实现的
- 获取bean
- BeanPostProcessor接口的实现类AnnotationAwareAspectJAutoProxyCreator对象,在postProcessAfterInitialization方法中获取bean生成代理方法。
- @EnableAspectJAutoProxy 将AnnotationAwareAspectJAutoProxyCreator对象加入spring容器
- 过滤bean,验证bean是不是需要被代理
在AnnotationAwareAspectJAutoProxyCreator.postProcessAfterInitialization中完成
-
将@Before等注解生成拦截方法对象,待后面调用目标方法时调用
- spring会将@Before等注解方法和切入点封装成PointcutAdvisor对象
- 实际上每个切面是一个List的集合
- @Before等注解方法被封装成Advice对象(实际上是MethodInterceptor),切入点被封装成Pointcut对象
- PointcutAdvisor,MethodInterceptor,Pointcut关系如下
四、总结
- BeanPostProcessor接口的实现对象AnnotationAwareAspectJAutoProxyCreator完成了aop
- @EnableAspectJAutoProxy注解引入了AnnotationAwareAspectJAutoProxyCreator