Spring AOP 的搭建与源码分析

一. AOP 概述

什么是 AOP : 指定程序在运行期间动态的将某段代码功能切入到指定的位置运行,底层是通过动态代理来实现的
AOP 优点 : 降低代码的耦合,提高代码复用性,提高系统的扩展性
AOP 常见使用场景 : 例如日志记录, 性能统计, 权限控制, 事物处理等

AOP 的实现步骤

  1. Spring 引入 AOP 需要的依赖
  2. 设置 Spring 开启 AOP 功能 (xml 方式开启,与注解方式开启)
  3. 创建存有需要通过 AOP 增强监管的业务代码,并注入到 Spring 容器中
  4. 创建 AOP 切面类,将切面类注入到 Spring 容器中,
  5. 告诉 Spring 容器,我是一个切面类 @Aspect
  6. 切面类中创建通知方法 :
    • 前置通知 @Before 目标方法执行前运行
    • 后置通知 @After 目标方法执行完毕,或抛出异常时运行
    • 返回通知 @AfterReturning 目标方法正常返回之后运行
    • 异常通知 @AfterThrowing 目标方法发生异常时运行
    • 环绕通知 @Around 该通知中可以获取到被监管的所有数据,可以获取到被监管执行的方法,在环绕通知方法中代理执行,所以可以自定义在被监管的方法前后添加需要执行的其他功能
  7. 设置通知方法在指定位置标注位置运行,切入点 (需要进行增强的业务代码位置, xml方式, 注解方式 @Pointcut(“execution()”)
    Spring 支持 AOP :需要添加依赖

示例

  1. Spring 中引入 AOP 依赖
		<dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-aop</artifactId>
                <version>${spring-version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-aspects</artifactId>
                <version>${spring-version}</version>
            </dependency>
  1. 配置 Spring 开启 AOP 功能
  • 注解方式,创建配置类,配置类使用 @EnableAspectJAutoProxy 注解修饰
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.*;

//通过配置类,使用注解的方式开启 Spring 的 aop 功能
@EnableAspectJAutoProxy
@Configuration
public class MyConfiguration {

}
  • xml 方式, resources 文件夹中创建.xml配置文件,配置文件中添加 aop:aspectj-autoproxy/ ,注意添加命名空间
<?xml version="1.0" encoding="UTF-8"?>
<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
xmlns:context="http://www.springframework.org/schema/context"

       xsi:schemaLocation="http://www.springframework.org/schema/beans"
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd" >

<!--开启aop-->
<aop:aspectj-autoproxy/>

<!--向Spring 容器中注入bean 的包扫描,原因是一般情况下
AOP 切面类与,controller,server,dao,不在一个包下,在使用注解
向spring中注入时,没有扫描,无法注入,如果在一个包下,或其它位置已经扫描过了,则可以不定义-->
<context:component-scan base-package="com.aop.自定义切面类所在的包" />

</beans>

  1. 创建业务类,编写业务代码,假设在业务代码执行前后,或发生异常时通过 AOP 增加其它功能
@Controller
public class TestController2 {

    @RequestMapping(value = "/aoptest", method = RequestMethod.GET)
    @ResponseBody
    public void aoptest(){
        System.out.println("我是被监管的业务代码......");
    }
}
  1. 创建切面类,将切面类注入到 Spring 容器中, 告诉 Spring 我是一个切面类,设置切入点,注入切入点扫描的目标方法所在路径是否正确,定义通知方法
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Aspect //1.代表该类时切面类
@Component //2.将切面类注入到 Spring 容器中
public class LogCut {

    //3.定义切入点方法,方法上添加@Pointcut()注解,设置当前切面类监管的目标方法位置
    //为了方便可以单独修饰一个空方法,然后通知注解上引用这个方法,也可以直接修饰通知方法
    /*解释:execution代表是个表达式
     * 扫描 com.ssm.controller 包下的所有类的所有方法
     * 第一个星的位置:代表这个方法的权限修饰符,星为任何权限都可以
     * com.com.controller 代表哪个包下的
     * controller 后的点有两个:一个代表该包下的根目录下的直接类中方法不包括子包
     * 两个点代表包括该包下的子包中类的方法
     * 点后的第一个星号位置代表包下的类,此处为星号代表任意类
     * 第二个星号位置代表方法,此处为星号代表任意方法
     * 括号中的两个点,为方法传入的参数类型,此处为两个点代表任意参数*/
    @Pointcut("execution(* com.ssm.controller..*.*(..))")
    public void cut() {
    }

    //4.定义通知方法,方法上添加对应的注解,

    //前置通知,设置前置通知监管的目标方法
    //如果被监管的目标方法有参数需要获取,可以在通知
    //方法中定义一个 JoinPoint 的形参,通过这个参数
    //可以拿到目标方法的相关数据,注意点 JoinPoint
    //这个参数一定要放在形参的第一个位置,否则报错
    @Before("cut()")
    public void before(JoinPoint joinPoint) {
        //获取目标方法签名
        Signature signature = joinPoint.getSignature();
        //获取目标方法签名获取方法参数
        Object [] args = joinPoint.getArgs();
        //通过目标方法签名获取目标方法名
        String name = signature.getName();

        System.out.println("前置通知方法执行,监管了"+name);
    }


    
    //返回通知,目标方法如果出现异常没有执行完毕,该通知方法不会执行
    //@AfterReturning("cut()")
    //如果被监管的方法有返回值,需要获取方法执行后的返回值,可以返回通知注解中
    //设置 returning 属性,属性值是返回的数据名,然后在方法形参中定义与该值同名的接收对象
    @AfterReturning(value = "cut()", returning = "result")
    public void afterReturn(JoinPoint joinPoint, Object result) {
        System.out.println("返回通知,正常完毕会执行该方法");
    }

    //后置通知,不管目标类方法是否发生异常,该通知方法都会执行
    @After("cut()")
    public void after() {
        System.out.println("后置通知,不管是否执行完毕,都会执行");
    }

    //异常通知目标类方法执行时发生异常执行,
    //throwings 代表目标方法抛出的异常,注解中 throwing的值要与方法中形参相同
    @AfterThrowing(value = "cut()", throwing = "e")
    public void afterThrowing(JoinPoint joinPoint, Exception e) {
        System.out.println("异常通知,发生异常时执行该终止" + e);
    }


    //环绕通知,目标方法执行前后,都可以做出相应的处理
    //环绕通知方法中需要传入一个ProceedingJoinPoint对象,该对象可以看为被拦截的方法对象
    //在该通知方法中,通过 ProceedingJoinPoint 对象,手动的调用目标方法,
    //这样就可以在目标方法前后添加其它操作了
    //注意环绕通知与异常通知配合使用时,环绕通知中的逻辑处理如果异常,方法执行后的代码会失效
    @Around("cut()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("环绕通知的前置执行");
        //通过环绕通知中传入的ProceedingJoinPoint对象可以获取目标类对象中的所有数据
        //pjp.getTarget()方法获取到的是目标类对象的内存信息(可以理解为可以获取到目标对象)
        //pjp.getSignature()方法可以获取到被代理类的方法
        System.out.println(pjp.getTarget() + "----" + pjp.getSignature());
        //只需目标方法,被拦截方法执行后执行?(为什么注释了该方法还是会执行后面的)
        Object result = pjp.proceed();
        System.out.println("环绕通知的后置执行");
        return result;
    }
}

  1. 此时如果 TestController2 类中的 aoptest() 方法,被切入点扫描,如果该方法执行,对应的通知方法也会执行

二. 通过 @EnableAspectJAutoProxy 了解 AOP 原理

@EnableAspectJAutoProxy 注解方式,开启 Spring 的 AOP 功能,查看该注解的源码
在这里插入图片描述

1. 分析 @EnableAspectJAutoProxy

  • 使用 @Import() 修饰,该注解中传递了一个 AspectJAutoProxyRegistrar 类 ,
  • 查看 AspectJAutoProxyRegistrar 类,通过该类中的 registerBeanDefinitions() 方法,使用 @Import() 在容器启动时向容器中注入一个 AnnotationAwareAspectJAutoProxyCreator 这是一个注解模式装配切面的自动代理创建器(注入过程了解@Import注入的几种方式)
  • 分析 AnnotationAwareAspectJAutoProxyCreator 类的继承关系
 AnnotationAwareAspectJAutoProxyCreator
	---->|AnnotationAwareAspectJAutoProxyCreator
	--------->|AbstractAdvisorAutoProxyCreator
    --------------->|AbstractAutoProxyCreator
	-------------------------->| ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware
	(其中 SmartInstantiationAwareBeanPostProcessor 又继承了 InstantiationAwareBeanPostProcessor
	InstantiationAwareBeanPostProcessor又继承了BeanPostProcessor)
	

发现 AnnotationAwareAspectJAutoProxyCreator 间接实现了SmartInstantiationAwareBeanPostProcessor 与 BeanFactoryAware接口

注意点 SmartInstantiationAwareBeanPostProcessor 继承了InstantiationAwareBeanPostProcessor 继承了BeanPostProcessor,InstantiationAwareBeanPostProcessor 与BeanPostProcessor不同的是增加了一个 postProcessBeforeInstantiation(),抽象方法,这个方法是在被监管的bean创建前执行的,这些后置处理器相关的方法在 AnnotationAwareAspectJAutoProxyCreator 的父类 AbstractAutoProxyCreator 中进行了实现,并且 bean 初始化前执行的方法 postProcessBeforeInitialization() 没做任何操作,直接进行了返回

  • AnnotationAwareAspectJAutoProxyCreator 间接实现了SmartInstantiationAwareBeanPostProcessor 后置处理器接口,该接口又继承自InstantiationAwareBeanPostProcessor接口,这个接口又继承了BeanPostProcessor接口,那么AnnotationAwareAspectJAutoProxyCreator 类就可以看为是一个后置处理器
  • AnnotationAwareAspectJAutoProxyCreator 类间接实现 BeanFactoryAware 接口,在AbstractAutoProxyCreator父类中重写 了setBeanFactory()方法,获取容器中的 BeanFactory
  • 根据继承关系由最上层父类开始查看,下级子类中是否重写了这两个接口中的抽象方法,下级子类的下级子类,是否有对这些方法再次进行了覆盖等,找到真实调用的那个

2.复习 Spring 容器启动后 bean 的注入执行过程,了解 AnnotationAwareAspectJAutoProxyCreator 的注入

  • Spring 容器启动注入bean时,首先会将直接或间接继承 BeanPostProcessor 接口的 bean 创建 初始化,注入到容器中,Spring 默认提供了一个实现 BeanPostProcessor 接口的 ApplicationContextAwareProcessor 后置处理器,每个 bean 的创建都会被该后置处理器监控到,执行初始化bean之前要执行的方法postProcessBeforeInitialization(),在方法中调用 invokeAwareInterfaces() 方法,判断当前要创建的 bean 是否是 Aware 的直接子类或间接子类,如果是,在 调用这个 bean 重写的 Aware 中的抽象方法,获取 Spring 自己的组件赋值当前要创建的 bean 对象
  • AnnotationAwareAspectJAutoProxyCreator 间接继承了 BeanFactoryAware 接口,在创建这个bean时,被ApplicationContextAwareProcessor 中的 invokeAwareInterfaces() 判断到,方法中调用重写BeanFactoryAware 接口中的 setBeanFactory() 方法获取 Spring 提供的 BeanFactory ,并且 AnnotationAwareAspectJAutoProxyCreator 间接继承了 BeanPostProcessor接口
  • 自此 AnnotationAwareAspectJAutoProxyCreator 持有 BeanFactory 先一步注入到了 Spring容器中

3.通过 AnnotationAwareAspectJAutoProxyCreator 生成代理对象

此时 AnnotationAwareAspectJAutoProxyCreator 已经创建注入到了容器中,开始创建其它 bean

  1. Spring 创建 IOC 容器,在创建容器时调用 AbstractApplicationContext 中的 refresh() 方法刷新容器
  2. 在 refresh() 方法中首先调用 registerBeanPostProcessors()该方法首先向容器中注册所有继承了 BeanPostProcessor 的 bean(包括间接继承与直接继承,Spring 自己提供的,与自定义创建的,后续的创建bean对象的步骤与下面 finishBeanFactoryInitialization()方法中的相同) , 然后调用 finishBeanFactoryInitialization() 方法创建所有单例对象(BeanPostProcessor 以外的单实例对象?)
  3. 在finishBeanFactoryInitialization() 方法中会获取到一个ConfigurableListableBeanFactory 类型的对象beanFactory,通过这个对象默认调用它的实现子类 DefaultListableBeanFactory 中的 preInstantiateSingletons()方法
  4. 在DefaultListableBeanFactory 的 preInstantiateSingletons() 方法中会通过 while 循环调用AbstractBeanFactory的 getBean(beanName)方法, 在 getBean() 方法中调用 doGetBean() 方法中会通过 getSingleton() 方法去获取 bean, 如果首次执行时,没有这个 bean, 则调用AbstractAutowireCapableBeanFactory 子类实现的 createBean() 方法,在createBean()方法中通过调用 doCreateBean()
  5. .createBean()方法中在调用doCreateBean()方法以前首先会调用 resolveBeforeInstantiation(beanName, mbdToUse); 通过后置处理器,创建当前 ben 的代理对象返回
  6. doCreateBean() 方法中首先调用会调用 populateBean() 方法, 对创建的 bean 的属性赋值 ,然后调用 initializeBean() 方法,执行创建这个 bean 的初始化方法
  7. initializeBean() 方法中先后调用了三个主要的方法 :
    - applyBeanPostProcessorsBeforeInitialization() 执行初始化前的方法,
    - invokeInitMethods() 执行初始化方法,例如我们自定义的一些初始化方法,框架中定义的一些初始化方法
    - applyBeanPostProcessorsAfterInitialization() 执行初始化后的方法
    - 初始化前后的方法执行,主要是判断需要初始化的bean是否是 BeanPostProcessor 的实现子类,如果是,在初始化前,调用执行 postProcessBeforeInitialization() 方法, 在初始化后,调用执行 postProcessAfterInitialization() 方法

createBean() 方法源码:

protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("Creating instance of bean '" + beanName + "'");
        }

        RootBeanDefinition mbdToUse = mbd;
        Class<?> resolvedClass = this.resolveBeanClass(mbd, beanName, new Class[0]);
        if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
            mbdToUse = new RootBeanDefinition(mbd);
            mbdToUse.setBeanClass(resolvedClass);
        }

        try {
            mbdToUse.prepareMethodOverrides();
        } catch (BeanDefinitionValidationException var7) {
            throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", var7);
        }

        Object beanInstance;
        try {
        	//======通过后置处理器,创建 当前需要创建的 bean 的代理对象并返回================
            beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse);
            //==========================================================================
            if (beanInstance != null) {
                return beanInstance;
            }
        } catch (Throwable var8) {
            throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", var8);
        }
		
		//=============创建 bean ===============
        beanInstance = this.doCreateBean(beanName, mbdToUse, args);
        //======================================================
        
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("Finished creating instance of bean '" + beanName + "'");
        }

        return beanInstance;
    }

resolveBeforeInstantiation() 方法源码: 在调用createBean() 创建 bean 对象时,首先调用该方法,通过该方法创建 当前 bean 的代理对象注入到容器中
在 resolveBeforeInstantiation() 方法中调用了: applyBeanPostProcessorsBeforeInstantiation()

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
        Object bean = null;
        if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
            if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
                Class<?> targetType = this.determineTargetType(beanName, mbd);
                if (targetType != null) {
                
                    bean = this.applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                    if (bean != null) {
                        bean = this.applyBeanPostProcessorsAfterInitialization(bean, beanName);
                    }
                }
            }

            mbd.beforeInstantiationResolved = bean != null;
        }

        return bean;
    }
  • applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);该方法会获取容器中所有后置处理器,遍历判断获取到的后置处理器是否有 InstantiationAwareBeanPostProcessor 类型的,如果有获取该后置处理器,调用创建 ben 对象前要执行的方法 postProcessBeforeInstantiation(beanClass, beanName); 方法,通过该方法创建出当前要创建的 bean 的代理类对象并返回
  • AOP 中 通过 @EnableAspectJAutoProxy 向容器中注入的 AnnotationAwareAspectJAutoProxyCreator 间接继承了 InstantiationAwareBeanPostProcessor 接口,判断通过,执行 postProcessBeforeInstantiation() 方法
    在这里插入图片描述

postProcessBeforeInstantiation() 后置处理器中,创建 bean 对象前自动执行的方法

  1. 判断要创建的bean 是否在 advisedBeans 中, advisedBeans中保存了所有要增强的bean
  2. 判断当前要创建的bean 是否是基础类型的,是否是切面类
  3. 判断是否需要跳过,shouldSkip() 调用的是AspectJAwareAdvisorAutoProxyCreator 中的,什么时候需要跳过,例如创建的bean是通知方法包装的增强器时…
    自己理解
    该方法中对于AOP 相关的并没有什么实际意义上的执行,只是进行了一些判断,如果判断不通过,将需要创建的bean存入advisedBeans集合中,并标识为false,不用增强,后续创建这个bean时,就不会对这个bean进行代理处理
  4. 当该方法执行完毕后,没有创建bean,createBean() 方法继续向下执行调用doCreateBean() 方法,调用目标类对象构造器,创建bean, 创建成功后,执行 AnnotationAwareAspectJAutoProxyCreator 中的 postProcessAfterInitialization()
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        Object cacheKey = this.getCacheKey(beanClass, beanName);
        if (beanName == null || !this.targetSourcedBeans.contains(beanName)) {
        	//是否在 advisedBeans 中
            if (this.advisedBeans.containsKey(cacheKey)) {
                return null;
            }
			//是否是基础类型的,是否是切面 || 判断是否需要跳过
			//当向advisedBeans中存储当前bean,并未false时,说明创建的这个bean不需要增强处理
            if (this.isInfrastructureClass(beanClass) || this.shouldSkip(beanClass, beanName)) {
                this.advisedBeans.put(cacheKey, Boolean.FALSE);
                return null;
            }
        }

        if (beanName != null) {
            TargetSource targetSource = this.getCustomTargetSource(beanClass, beanName);
            if (targetSource != null) {
                this.targetSourcedBeans.add(beanName);
                Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
                Object proxy = this.createProxy(beanClass, beanName, specificInterceptors, targetSource);
                this.proxyTypes.put(cacheKey, proxy.getClass());
                return proxy;
            }
        }

        return null;
    }

postProcessAfterInitialization(); 后置处理器中,调用 bean 构造器,创建对象成功后,初始化 bean 后自动执行的方法

(初始化前执行的方法,在 AOP 相关设计中没做任何操作)

 public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean != null) {
            Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
            //判断是否已经代理过了
            if (!this.earlyProxyReferences.contains(cacheKey)) {
                return this.wrapIfNecessary(bean, beanName, cacheKey);
            }
        }

        return bean;
    }
 protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
            return bean;
            //判断是否是已经在advisedBeans中集合中,该集合中存放了被标识为不用增强的和已经增强过的bean
        } else if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
            return bean;
          	//判断是否是切面类  
        } else if (!this.isInfrastructureClass(bean.getClass()) && !this.shouldSkip(bean.getClass(), beanName)) {
        	//获取当前 bean 可以使用的增强器也就是通知方法,并根据前置通知,后置通知...对增强器进行排序(通过切入点匹配监管当前bean的通知方法)
            Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);
            if (specificInterceptors != DO_NOT_PROXY) {
            	//记录当前bean 已被增强处理
                this.advisedBeans.put(cacheKey, Boolean.TRUE);
                //创建当前 bean 的代理对象
                Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
                this.proxyTypes.put(cacheKey, proxy.getClass());
                return proxy;
            } else {
                this.advisedBeans.put(cacheKey, Boolean.FALSE);
                return bean;
            }
        } else {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }
    }
protected Object createProxy(Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
        if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
            AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory)this.beanFactory, beanName, beanClass);
        }
		//创建一个代理创建工厂
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.copyFrom(this);
        if (!proxyFactory.isProxyTargetClass()) {
            if (this.shouldProxyTargetClass(beanClass, beanName)) {
                proxyFactory.setProxyTargetClass(true);
            } else {
                this.evaluateProxyInterfaces(beanClass, proxyFactory);
            }
        }
		//获取监管当前bean的所有增强器通知方法
        Advisor[] advisors = this.buildAdvisors(beanName, specificInterceptors);
        Advisor[] var7 = advisors;
        int var8 = advisors.length;

        for(int var9 = 0; var9 < var8; ++var9) {
            Advisor advisor = var7[var9];
            //将增强器保存到代理工厂中
            proxyFactory.addAdvisor(advisor);
        }

        proxyFactory.setTargetSource(targetSource);
        this.customizeProxyFactory(proxyFactory);
        proxyFactory.setFrozen(this.freezeProxy);
        if (this.advisorsPreFiltered()) {
            proxyFactory.setPreFiltered(true);
        }
		//获取代理对象
        return proxyFactory.getProxy(this.getProxyClassLoader());
    }

创建代理类

扫描二维码关注公众号,回复: 10985774 查看本文章
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
        	//JDK 动态代理
            return new JdkDynamicAopProxy(config);
        } else {
            Class<?> targetClass = config.getTargetClass();
            if (targetClass == null) {
                throw new AopConfigException("TargetSource cannot determine target class: Either an interface or a target is required for proxy creation.");
            } else {
            	//Cglib 动态代理 ObjenesisCglibAopProxy(config)
                return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config));
            }
        }
    }

在执行目标方法时,获取目标方法的所有增强器通知方法,将增强器包装为 MethodInterceptor 拦截器链,然后使用拦截器链,与目标方法中包含的数据,执行时在代理类中获取所有拦截器,判断是否有拦截器,是否该执行目标方法,如果没有拦截器,或执行到了目标方法位置,通过反射,执行目标方法,如果有拦截器,执行拦截器

三. AOP 总结

AOP 的搭建步骤

  1. Spring 中引入 AOP 相关依赖
  2. Spring 设置开启 AOP
  3. 创建 AOP 切面类,将界面类注入到容器中
  4. 切面类中编写通知方法
  5. 设置切入点,将通知方法织组目标方法

AOP 原理

  1. 通过 @EnableAspectJAutoProxy 注解设置 Spring 开启 AOP 了解到,在使用 AOP 时,会向 Spring 容器中注入一个AnnotationAwareAspectJAutoProxyCreator 后置处理器, AnnotationAwareAspectJAutoProxyCreator 间接实现了 InstantiationAwareBeanPostProcessor 与 BeanFactoryAware 接口,
    InstantiationAwareBeanPostProcessor 又继承了 BeanPostProcessor 接口,与 BeanPostProcessor 不同的是,该接口中增加了一个 postProcessBeforeInstantiation() 抽象方法, 该方法是监控在创建bean以前执行的
  2. 分析 AnnotationAwareAspectJAutoProxyCreator 间接实现 BeanFactoryAware 接口, 是为了拿到 Spring 提供的BeanFactory ,因为 Spring 在提供容器时默认提供了一个 ApplicationContextAwareProcessor 后置处理器,注入到了容器中,在后续初始化 bean 时,都会被这个后置处理器监控到执行初始化的方法,判断当前要创建的 bean 是否是InstantiationAwareBeanPostProcessor 类型,如果是执行invoke() 方法,判断当前要创建的 bean 是否实现了某个 Aware 接口,如实现了,调用重写的该接口中的抽象方法获取, 获取Spring 提供的组件,此处获取的是 BeanFactory
  3. 分析 AnnotationAwareAspectJAutoProxyCreator 间接继承 InstantiationAwareBeanPostProcessor 接口,当前这个类就就是一个后置处理器,在该类的 AbstractAutoProxyCreator 父类中实现了后置处理器监控 bean 的创建前执行的方法,初始化前执行的方法与初始化后执行的方法
  4. Spring 容器在创建时调用 refresh() 方法刷新容器,方法中创建获取创建 bean 时,首先调用registerBeanPostProcessors() 方法,将直接或间接继承了 BeanPostProcessor 接口的 bean 创建注入到容器中,也就是 IOC 容器在创建注入 bean 时会首先创建注入后置处理器,然后调用 finishBeanFactoryInitialization() 方法创建其他所有单例对象,自此 AnnotationAwareAspectJAutoProxyCreator 这个后置处理器,就先一步获取到 BeanFactory 创建注入到了容器中
  5. 后续再创建其它 bean 时,在creatBean方法中(),首先会调用 resolveBeforeInstantiation(beanName, mbdToUse) 方法,获取所有后置处理器,循环判断是否存在InstantiationAwareBeanPostProcessor 这个类型的后置处理器 AnnotationAwareAspectJAutoProxyCreator 是该类型的实现子类,如果是调用执行创建 bean 以前的方法 postProcessBeforeInstantiation()
  • postProcessBeforeInstantiation() 创建 bean 以前执行的方法 : 该方法在 AOP 相关的处理中并没有太多实际的动作,只是判断当前 bean 是否是切面类,是否是增强器(也就是切面类中的通知方法,在Spring 容器启动时,会将切面中的通知方法封装成一个个的增强器),是否允许被增强,如果不允许增强,将当前类放入一个集合中 advisedBeans,中并标识为false,不允许增强
  • postProcessBeforeInitialization() 初始化 bean 以前执行的方法,该方法在此处没有任何操作,直接进行了返回
  • postProcessAfterInitialization() 初始化 bean 后执行的方法,该方法中调用判断当前要创建的 bean 是否允许增强处理,是否已经被增强处理,创建ProxyFactory代理类工厂,通过切入点匹配获取监管当前 bean 的所有增强器(通知方法)将获取到的通知方法存入代理工厂中,通过 JDK 动态代理,或 Gglib 动态代理生成代理对象
  1. 执行 在执行目标方法时,获取目标方法的所有增强器通知方法,将增强器包装为 MethodInterceptor 拦截器链,如果有拦截器执行拦截器,如果没有通过反射执行目标方法?
发布了48 篇原创文章 · 获赞 0 · 访问量 581

猜你喜欢

转载自blog.csdn.net/qq_29799655/article/details/105325591