首先,从一个简单的案例走起

切面

  1. @Aspect
  2. public class LogAspects {
  3. //抽取公共的切入点表达式
  4. //1、本类引用
  5. //2、其他的切面引用
  6. @Pointcut("execution(public int cn.spectrumrpc.aop.MathCalculator.*(..))")
  7. public void pointCut(){};
  8. //@Before在目标方法之前切入;切入点表达式(指定在哪个方法切入)
  9. @Before("pointCut()")
  10. public void logStart(JoinPoint joinPoint){
  11. Object[] args = joinPoint.getArgs();
  12. System.out.println(""+joinPoint.getSignature().getName()+"运行。。。@Before:参数列表是:{"+Arrays.asList(args)+"}");
  13. }
  14. @After("pointCut()")
  15. public void logEnd(JoinPoint joinPoint){
  16. System.out.println(""+joinPoint.getSignature().getName()+"结束。。。@After");
  17. }
  18. //JoinPoint一定要出现在参数表的第一位
  19. @AfterReturning(value="pointCut()",returning="result")
  20. public void logReturn(JoinPoint joinPoint,Object result){
  21. System.out.println(""+joinPoint.getSignature().getName()+"正常返回。。。@AfterReturning:运行结果:{"+result+"}");
  22. }
  23. @AfterThrowing(value="pointCut()",throwing="exception")
  24. public void logException(JoinPoint joinPoint,Exception exception){
  25. System.out.println(""+joinPoint.getSignature().getName()+"异常。。。异常信息:{"+exception+"}");
  26. }
  27. }
  1. public class MathCalculator {
  2. public int div(int i,int j){
  3. System.out.println("MathCalculator...div...");
  4. return i/j;
  5. }
  6. }

MainConfig

  1. @EnableAspectJAutoProxy
  2. @Configuration
  3. public class MainConfigOfAOP {
  4. //业务逻辑类加入容器中
  5. @Bean
  6. public MathCalculator calculator(){
  7. return new MathCalculator();
  8. }
  9. //切面类加入到容器中
  10. @Bean
  11. public LogAspects logAspects(){
  12. return new LogAspects();
  13. }
  14. }

测试类

  1. @Test
  2. public void test01(){
  3. AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAOP.class);
  4. MathCalculator mathCalculator = applicationContext.getBean(MathCalculator.class);
  5. mathCalculator.div(1, 0);
  6. applicationContext.close();
  7. }

主要因为@EnableAspectJAutoProxy

那我们就看看这个类到底干了些什么东西

  1. @Target(ElementType.TYPE)
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Documented
  4. @Import(AspectJAutoProxyRegistrar.class)
  5. public @interface EnableAspectJAutoProxy

在这个上面,看到了@Import注解,众所周知,@Import可以为容器导入组件。紧接着,就看看导入的 AspectJAutoProxyRegistrar 为我们干了些什么

首先,这个类继承了@ImportBeanDefinitionRegistrar,可以在registerBeanDefinitions() 中导入组件

  1. class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar

所以,紧接着转向了 registerBeanDefinitions() 方法。在其中,有这么一句话

  1. AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
  2. // 调用 ->
  3. registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
  4. // 调用 ->
  5. registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
  6. // 往容器中添加了一个类型为 AnnotationAwareAspectJAutoProxyCreator 名称为 org.springframework.aop.config.internalAutoProxyCreator 的组件

那么,我们紧接着就又转向了 AnnotationAwareAspectJAutoProxyCreator 这个类

首先,看这个类的继承图谱,可以看出,其是一个后置处理器

image.png

在IOC容器启动时,将会调用后置处理器相应的方法。其中 如果后置处理器的类型是 InstantiationAwareBeanPostProcessor 将会调用 postProcessBeforeInstantiation 前置方法 。 postProcessAfterInitialization 后置方法。

  1. protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
  2. for (BeanPostProcessor bp : getBeanPostProcessors()) {
  3. if (bp instanceof InstantiationAwareBeanPostProcessor) {
  4. InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
  5. Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
  6. if (result != null) {
  7. return result;
  8. }
  9. }
  10. }
  11. return null;
  12. }
  13. public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
  14. throws BeansException {
  15. Object result = existingBean;
  16. for (BeanPostProcessor processor : getBeanPostProcessors()) {
  17. Object current = processor.postProcessAfterInitialization(result, beanName);
  18. if (current == null) {
  19. return result;
  20. }
  21. result = current;
  22. }
  23. return result;
  24. }

在这AbstractAutoProxyCreator 中的这两个方法,其中的处理流程如下:

  1. // 1. 获取 该类的切面方法
  2. Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
  3. // 2. 为这个类创建代理,默认是cglib动态代理
  4. createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));

创建代理完成之后,将代理对象返回

在执行目标类的目标方式时,将会直接代理对象的 DynamicAdvisedInterceptor 的 intercep 方法

  1. // 1. 首先获取这个方法上的切面
  2. this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
  3. // 2.
  4. new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
  5. // 3. 会依次调用所有处理链的invoke方法,具体的流程如下:

查看这几个切面类的invoke方法即可知道,对应的AOP的前置通知,后置通知,返回通知,异常通知的实现结果,其原理是通过处理链的执行时机来决定的。

image.png