Spring注解开发(十)——AOP小实践&源码初步分析之注册AnnotationAwareAspectJAutoProxyCreator后置处理器

业务类:

package com.cjian.aop;

/**
 * @description:
 * @author: cWX969834
 * @time: 2020/11/4 9:06
 */
public class MathCalculator {

    public int div(int a, int b) {
        System.out.println("除法。。。");
        return a / b;
    }

}

 切面类:

package com.cjian.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

import java.util.Arrays;

/**
 * @description:切面类,业务增强类
 * @author: cWX969834
 * @time: 2020/11/4 9:07
 */
@Aspect
public class LogAspects {

    //抽取公共的切入点表达式
    //1.本类引用  如 logStart
    //2.外部类引用 如 logEnd
    @Pointcut("execution(public int com.cjian.aop.MathCalculator.*(..))")
    public void pointCut(){}

    //在方法运行之前
    @Before("pointCut()")
    public void logStart(JoinPoint jp) {
        System.out.println(jp.getSignature().getName()+" 开始运行..."+"参数为 :"+ Arrays.asList(jp.getArgs()));
    }

    //在方法运行之后(无论方法是否正常运行)
    @After("com.cjian.aop.LogAspects.pointCut()")
    public void logEnd(JoinPoint jp) {
        System.out.println(jp.getSignature().getName()+" 运行结束...");
    }
    //在方法正常运行之后
    @AfterReturning(value="pointCut()",returning = "result")
    public void logReturn(JoinPoint jp,Object result) {
        System.out.println(jp.getSignature().getName()+" 运行结束...结果为:"+result);
    }
    //在方法出现异常之后运行
    @AfterThrowing(value = "pointCut()",throwing = "exception")
    public void logException(JoinPoint jp,Exception exception) {
        System.out.println(jp.getSignature().getName()+" 发生异常..."+exception);
    }

}

配置类:

package com.cjian.config;

import com.cjian.aop.LogAspects;
import com.cjian.aop.MathCalculator;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

/**
 * @description:
 * @author: cWX969834
 * @time: 2020/10/28 9:32
 */
@Configuration //告诉spring这是一个配置类
@EnableAspectJAutoProxy//开启AOP
public class MainConfigAOP {

    @Bean
    public MathCalculator mathCalculator(){
        return new MathCalculator();
    }

    @Bean
    public LogAspects logAspects(){
        return new LogAspects();
    }

}

测试类:

package com.cjian;

import com.cjian.aop.MathCalculator;
import com.cjian.config.MainConfigAOP;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @description:
 * @author: cWX969834
 * @time: 2020/11/3 11:13
 */
public class TestAOP {

    static AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(
        MainConfigAOP.class);

    public static void main(String[] args) {
        MathCalculator mathCalculator = annotationConfigApplicationContext.getBean(MathCalculator.class);
        mathCalculator.div(1, 0);
    }
}

输出:

div 开始运行...参数为 :[1, 0]
除法。。。
div 发生异常...java.lang.ArithmeticException: / by zero
div 运行结束...
Exception in thread "main" java.lang.ArithmeticException: / by zero
......后面异常信息省略

正常运行时:

div 开始运行...参数为 :[1, 1]
除法。。。
div 运行结束...结果为:1
div 运行结束...

AOP的一个小实践就搞定了,那么AOP的原理是啥呢?

让我们从@EnableAspectJAutoProxy注解入手,看看这个注解都干了啥?

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({AspectJAutoProxyRegistrar.class})
public @interface EnableAspectJAutoProxy {
    boolean proxyTargetClass() default false;

    boolean exposeProxy() default false;
}

使用@Import注解给容器中注册了一个AspectJAutoProxyRegistrar,这个类是干啥的呢?

package org.springframework.context.annotation;

import org.springframework.aop.config.AopConfigUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.AnnotationMetadata;

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
    AspectJAutoProxyRegistrar() {
    }

    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        //重点,这里来个断点
        AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
        AnnotationAttributes enableAspectJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
        if (enableAspectJAutoProxy != null) {
            if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
                AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
            }

            if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
                AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
            }
        }

    }
}

debug发现通过几个方法的调用,最终来到了这里

 @Nullable
    private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
        //clas :org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        if (registry.containsBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator")) {
            BeanDefinition apcDefinition = registry.getBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator");
            if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
                int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
                int requiredPriority = findPriorityForClass(cls);
                if (currentPriority < requiredPriority) {
                    apcDefinition.setBeanClassName(cls.getName());
                }
            }

            return null;
        } else {
            RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
            beanDefinition.setSource(source);
            beanDefinition.getPropertyValues().add("order", -2147483648);
            beanDefinition.setRole(2);
            registry.registerBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator", beanDefinition);
            return beanDefinition;
        }
    }

为了给容器中注册一个id 为org.springframework.aop.config.internalAutoProxyCreator,实例为org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator 的组件

总结:@EnableAspectJAutoProxy 的功能?

通过@Import({AspectJAutoProxyRegistrar.class}) 给容器中导入了一个AspectJAutoProxyRegistrar,利用AspectJAutoProxyRegistrar自定义给容器中注册一个id 为org.springframework.aop.config.internalAutoProxyCreator,实例为org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator 的组件

那么 AnnotationAwareAspectJAutoProxyCreator又是什么呢?

查看该类的体系:

第一点不管它,主要看右边即第二点,关注后置处理器在bean初始化完成前后做了什么事,以及第三点自动装配BeanFactory

接下来我们重点关注每个类都干了什么,因为各种继承/实现关系,我们先从最顶层的父类即AbstractAutoProxyCreator开始分析:

发现有以下三我们需要重点关注的方法

 

接下来是AbstractAdvisorAutoProxyCreator,它又重写了父类的setBeanFactory方法,并在里面调用了initBeanFactory方法

接下来是AspectJAwareAdvisorAutoProxyCreator ,没有什么需要关注的,跳过

然后是AnnotationAwareAspectJAutoProxyCreator,这里它又重写了initBeanFactory方法,需要关注

 

创建和注册AnnotationAwareAspectJAutoProxyCreator的过程


1)、传入配置类,创建IOC容器
2)、注册配置类,调用refresh()刷新容器
3)、registerBeanPostProcessors(),注册bean的后置处理器来方便拦截bean的创建;

     1)、先获取ioc容器已经定义的需要创建对象的所有BeanPostProcessor


     2)、先给容器中加别的BeanPostProcessor
     3)、优先注册实现了PriorityOrdered接口的BeanPostProcessor

     4)、再给容器中注册实现了Ordered接口的接口的BeanPostProcessor

AnnotationAwareAspectJAutoProxyCreator实现了Ordered接口


     5)、注册没有实现优先级接口的接口的BeanPostProcessor
     6)、注册BeanPostProcessor,实际上就是创建BeanPostProcessor对象,保存在容器中;
             创建internalAutoProxyCreator的BeanPostProcessor【AnnotationAwareAspectJAutoProxyCreator】

PS:getBean最终会调用到org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean方法,该方法还涉及了spring的循环依赖问题,以后再说


          1)、创建Bean的实例;

finishBeanFactoryInitialization:完成BeanFactory初始化工作,创建剩下的单实例bean

doGetBean方法:先从缓存中获取当前bean,如果能获取到,说明bean之前被创建过,直接使用,否则再创建(只要创建好的bean都会被缓存起来这也是spring保证单实例只会被创建一次的机制)

 

         

AnnotationAwareAspectJAutoProxyCreator刚好是InstantiationAwareBeanPostProcessor的子类

最终来到这了,下面这张截图也是AnnotationAwareAspectJAutoProxyCreator的作用了,后面分析

 

          2)、populateBean:给bean的各种属性赋值;
          3)、initializeBean:初始化bean;该步骤之前说过,不再细说了
              1)、invokeAwareMethods:处理Aware接口的方法回调
              2)、applyBeanPostProcessorsBeforeInitialization
              3)、invokeInitMethods:执行自定义的初始化方法
              4)、applyBeanPostProcessorsAfterInitialization

          4)、BeanPostProcessor【AnnotationAwareAspectJAutoProxyCreator】创建成功,并调用initBeanFactory


  7)、把BeanPostProcessor注册到BeanFactory中:beanFactory.addBeanPostProcessor

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值