Spring源码——AOP的实现原理和运行流程

本章节采用的是全注解开发模式

一.AOP的概述

> AOP是Aspect Oriented Programming(面向切面编程),以解耦合的方式对service层的业务方法的功能增强

> AOP本身是一种思想,但是Spring框架实现了这种思想

> AOP的执行原理:利用动态代理创建代理对象,并将通知方法织入到切入点当中

二.AOP定义阶段的源码分析

(1)全注解状态下配置打开AOP的自动代理功能,会涉及到一个注解@EnableAspectJAutoProxy注解,功能是开启AOP的自动代理

@EnableAspectJAutoProxy //开始aop自动代理
@Configuration
public class AOPOpenConfig {
}

(2)@EnableAspectJAutoProxy的源代码

> 使用@Import注解导入了一个叫做AspectJAutoProxyRegistry

> 观察继承树体系发现其本身是一个BeanDefinitionRegistryPostProcessors增强器

@Import(AspectJAutoProxyRegistrar.class) // 导入类
public @interface EnableAspectJAutoProxy {

(3)debug AspectJAutoProxyRegistry

> 该类调用时机是在invokeBeanDefinitionRegistryPostProcessors(),调用bean实例定义信息处理器进行后置处理(容器刷新十二大步的invokeBeanFactoryPostProcessor())

invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());

> 执行postProcessBeanDefinitionRegistry()方法进行后置增强

postProcessor.postProcessBeanDefinitionRegistry(registry);

> 内部调用了processConfigBeanDefinition()方法来处理配置bean实例的定义信息

processConfigBeanDefinitions(registry); // 处理配置bean实例的定义信息

> this.reader.loadBeanDefinition() 【reader是配置类定义信息的读取器,加载bean实例信息】

this.reader.loadBeanDefinitions(configClasses);

> 调用 AspectJAutoProxyRegistry 注册AopConfig类的定义信息

AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

> 总结:AspectJAutoProxyRegistry是负责注册AnnotationAwareAspectJAutoProxyCreator

(4)AnnotationAwareAspectJAutoProxyCreator

> 观察继承树结构可以得知:该类是一个BeanPostProcessor(bean实例的后置处理器)

> 对该类的实例方法进行debug调试,观察其执行时机

> 第一次执行的方法是initBeanFactory()方法

[ 1 ] initBeanFactory()

        > 执行时机:registerBeanPostProcessor():容器刷新十二大步的注册bean实例后置处理器

        > 作用:传入beanFactory实例工厂,并设置一些关于AOP操作的属性       

        > 设置的属性:reflectiveAspectJAdvisiorFactory:准备创建增强器的工厂

                              aspectJAdvisiorsBuilder:准备建造者

if (this.aspectJAdvisorFactory == null) {
			this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory); 
// 准备一个ReflectiveAspectJAdvisorFactory作为切面增强器工厂
		}
		this.aspectJAdvisorsBuilder =
				new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory); //准备建造者

[ 2 ] isInfrastructureClass()

        > 执行时机:在注册后置处理器,完成beanFactory初始化完毕的时候会调用该方法

        > 作用:判断当前类是否为切面类,获取当前类上是否有配置切面注解的类

        > 原因:AnnotationAwareAspectJAutoProxyCreator 实现的接口有InstantiationAwareBeanPostProcessor

         

for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
			Object result = bp.postProcessBeforeInstantiation(beanClass, beanName); // bean实例实例化之前进行后置增强
			if (result != null) {
				return result;
			}
		}

 [ 3 ] findCandidateAdvisiors()下的buildAspectAdvisiors()

              > 执行时机:在bean实例或后置处理器初始化之后调用creator的后置处理方法时调用

              > 作用:根据 aspectBeanNames集合来获取到第一次获取到的切面类名字,获取到标注                > 切面注解的通知方法,也就是增强器

              > 操作范围:1、可以对单例对象操作 2、可以对原型对象(多例对象)操作

              > 执行流程:1、第一次执行该方法的时候,会获取容器中所有bean实例,遍历获取增强器,将其放到了缓存当中

              > 执行次数:每一个bean实例初始化的时候都会执行该方法

if (this.beanFactory.isSingleton(beanName)) { 
		this.advisorsCache.put(beanName, classAdvisors); 
}
else {
        this.aspectFactoryCache.put(beanName, factory);
}
advisors.addAll(classAdvisors);

                2、第二次或多次获取的时候,遍历切面类名集合,将名字作为key值获取增强器,放入到advisior()集合当中

	if (cachedAdvisors != null) { // 表示切面类是单例对象
				advisors.addAll(cachedAdvisors); // 缓存的增强器添加到增强器集合当中
			}

三、AOP在其他环节的准备操作

> 执行例子:debug 需要功能增强的业务类的业务方法】

 ApplicationContext context = new AnnotationConfigApplicationContext(Config1.class);
        HelloService bean = context.getBean(HelloService.class);
        bean.sayHello();

(1)首先,创建HelloService类,调用getBean()方法的时候

(2)bean实例创建之前,被resolveBeforeInstantiation()方法拦截,该方法是给用户一个机会返回一个bean实例的代理对象,Spring就不需要进行创建了

        涉及后置处理器类型:InstantiationAwareBeanPostProcessor

        关于AOP的后置处理器:creator本身也是一个 InstantiationAwareBeanPostProcessor

        执行流程:调用postProcessBeforeInstantiation()方法对bean实例后置增强

        功能:判断当前bean实例是否为切面类,获取到所有切面的增强器方法,观察是否有特殊的类

        总结:该后置增强方法并没有真正执行关于AOP的操作

(3)bean实例创建过程中,被 applyMergedBeanDefinitionPostProcessors()方法拦截

        > 涉及后置处理器类型: MergedBeanDefinitionPostProcessor

        > 关于AOP的后置处理器:creator不是一个  MergedBeanDefinitionPostProcessor

        > 总结:并没有真正任何关于AOP的操作

(4)bean实例属性赋值的时候,被 InstantiationAwareBeanPostProcessor处理器拦截

        > 关于AOP的后置处理器:creator本身是一个InstantiationAwareBeanPostProcessor

@Override
	public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
		return pvs;  // skip postProcessPropertyValues 返回bean实例的原生对象,可以说明并没有AOP并没有起作用
	}

        > postProcessProperties()方法本身只返回一个原生对象,所以也没有处理AOP流程

(5)至此,bean实例的自动装配环节到此结束

        > 说明:AOP的执行是在bean实例执行@Autowired注解自动装配环节之后的

(6)初始化bean实例的时候,被前置拦截

        > 涉及后置处理器类型:BeanPostProcessor

        > 关于AOP的后置处理器:creator本身是一个 BeanPostProcessor

        > 执行方法:beanPostProcessor.postProcessBeforeInitialization()

default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

        > 返回了bean实例原生对象,可以说明并没有真正执行AOP的操作

(7)bean实例初始化后,被后置拦截

        > 涉及后置处理器类型:BeanPostProcessor

        > 关于AOP的后置处理器:creator本身是一个BeanPostProcessor

        > 执行方法:beanPostProcessor.postProcessAfterInitialization()   

        > 以下可知:可以得知开始执行AOP的准备阶段了 ,重点分析

	@Override
	public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
		if (bean != null) {
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			if (this.earlyProxyReferences.remove(cacheKey) != bean) {
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}

(8)获取cacheKey值,并且执行wrapIfNecessary()方法

> 根据bean实例的class信息和beanName获取对该类切入点增强的增强器

Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);

> 寻找合法的增强器,并且进行条件判断(在getAdvicesAndAdvisiorsForBean())

List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName); // 找到合法的增强方法
		if (advisors.isEmpty()) {
			return DO_NOT_PROXY;
		}
		return advisors.toArray();

> 调用creator的findCandidateAdvisiors()获取候选的增强器,并且判断是否可以切入

        > 返回的增强器是六个,Spring内部注入了一个ExposeInvocationInterceptor()

List<Advisor> candidateAdvisors = findCandidateAdvisors(); // 从缓存拿到所有切面的增强器
		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); // 看增强器能不能引用到这个实例上
		extendAdvisors(eligibleAdvisors);
		if (!eligibleAdvisors.isEmpty()) {
			eligibleAdvisors = sortAdvisors(eligibleAdvisors); // 对增强器的执行顺序进行一个排序
		}
		return eligibleAdvisors;

> 执行上述两个方法之后,重点操作

        > 由于特定拦截器不为空,所以为其创建代理对象

        > 执行操作:获取增强器,获取代理工厂,为代理工厂设置一系列的属性

        > 最终,返回结果的时候使用代理工厂创建代理对象

if (specificInterceptors != DO_NOT_PROXY) {
			this.advisedBeans.put(cacheKey, Boolean.TRUE); // 将bean实例添加到已经增强的bean实例当中
			Object proxy = createProxy(
					bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); // 创建代理
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}
return proxyFactory.getProxy(classLoader);

        > 观察getProxy方法的时候,发现创建方式是cglib动态代理模式

// Configure CGLIB Enhancer...
			Enhancer enhancer = createEnhancer();

        > 执行完上述方法,创建代理对象的操作结束

(9)至此,创建完带有增强器方法的代理对象,AOP的准备阶段就已经结束了

四.AOP的运行流程

(1)调用IOC容器的getBean获取到代理对象,具体的获取步骤就不展示了

(2)执行切入点方法sayHello()方法

(3)由于HelloService对象是cglib代理对象,执行interceptor()回调方法

(4)执行方法的重点步骤proceed()

retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed(); // proceed才是真正执行的关键

(5)调用父类的模板方法proceed()

return super.proceed(); // 调用父类的模板方法

(6)观察可知:proceed()执行的时候采用的是递归调用的方式,由于该步骤较为长,因此对此使用流程图的方式来

         > 建议:一边跟着流程图,一边可以比对所给的流程图,您会发现新世界

 链接:https://pan.baidu.com/s/1e1oZ8zxjCPG-7G4LN2hLeA 
提取码:obr6 
--来自百度网盘超级会员V3的分享

 (7)至此,AOP的操作就到此结束了

五.总结

1、源码分析流程是我个人花费一个星期去一个一个分析出来,如果有不足的话,请大佬们指出

2、也希望你们能仔细看一下

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值