码迷,mamicode.com
首页 > 编程语言 > 详细

spring源码分析——Aop的流程

时间:2020-07-06 12:39:45      阅读:70      评论:0      收藏:0      [点我收藏+]

标签:oid   单例对象   link   完成   结果   根据   实现原理   maps   figure   

 

  上面章节我们花费了大量的时间分析IOC,控制反转,反转控制对象的创建以及维护对象之间的依赖关系,对象的销毁

1:对象的创建,加载并解析xml文件或者注解,生成BeanDefinition对象,实例化BeanDefinitionRegistryPostProcessor并调用重写方法,实例化并注册BeanPostProcessor 

的后置接口,预实例化非懒加载的单例对象。

2:维护对象的依赖关系, set注入、构造器注入、@Autowired 的依赖注入等

3:对象的销毁,注册可销毁的回调接口,以及销毁接口的调用

 

一:Aop的使用

下面我们来重点分析一下Aop的实现原理,首先我们来看一下面向切面编程的使用,

技术图片

 

 

技术图片

 

 

测试代码:

技术图片

 

 从运行结果看方法被拦截,说明代理成功:

 

技术图片

 

 

二:源码层面分析Aop

1:看一下开启Aop的配置具体做了什么,这是一个自定义标签aop,是通过命名空间加载的handler处理类

技术图片

 

 

spring.handlers处理类

 

技术图片

 

 

public class AopNamespaceHandler extends NamespaceHandlerSupport {

	/**
	 * Register the {@link BeanDefinitionParser BeanDefinitionParsers} for the
	 * ‘{@code config}‘, ‘{@code spring-configured}‘, ‘{@code aspectj-autoproxy}‘
	 * and ‘{@code scoped-proxy}‘ tags.
	 * AopNamespaceHandler 命名空间handler实例化完成后,会调用init进行初始化,
	 * 在初始化中完成各种元素解析器的注册
	 */
	@Override
	public void init() {
		// In 2.0 XSD as well as in 2.1 XSD.
		registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
		registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
		registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());

		// Only in 2.0 XSD: moved to context namespace as of 2.1
		registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
	}

}

    

处理器init方法中,有一个AspectJAutoProxyBeanDefinitionParser的解析器:

技术图片

 

 

技术图片

 

 技术图片技术图片

 

 

技术图片

 

 AnnotationAwareAspectJAutoProxyCreator 这个类将会被注册到BeanDefinitionMaps中

 

 

 技术图片

 

 到这里动态代理的BeanPostProcessor以BeanDefinition的形式注册到BeanDefinitionMaps中就完成了。

 

2:在refresh方法中,registryBeanPostProcessor方法中,会实例化所有的BeanPostProcessor对象,并注册到beanPostProcessors中,以备后续使用。

 

3:使用BeanPostProcessor创建代理对象

创建代理对象是在initializeBean方法中beanPostProcessor的after接口中进行的

技术图片

 

 调用代理PostProcessor的后置接口方法:

技术图片

 

 

这wrapIfNecessary中进行代理:

技术图片

 

 

获取切面通知,并创建代理,然后返回,大致的流程是这样,我们再来看一下细节部分:

技术图片

 

 

获取切面通知:

技术图片

 

 技术图片

 

 寻找所有切面类:

技术图片

 

 

寻找切面类的所有增强:

技术图片

 

 

搜集切面类的所有非切点方法:

技术图片

 

 

技术图片

 

 每个Advisor维护了Advice对象

技术图片

 

 

getAdvice方法:

技术图片

 

 根据注解类型 判断 是创建Before 、After、Around 的通知器Advice

到这里就把所有的@Aspect类里所有的非切点方法,搜集到了,封装成Advisor对象,每个Advisor对象维护了一个Advice对象。

 

看一下和当前bean的匹配

技术图片

 

 

技术图片

 

 

匹配当前类:

技术图片

 

 技术图片

 

 

技术图片

 

 将匹配的Advisor返回,到这里所有匹配的bean的增强通知器Advisor都被搜集到了。

 

下一步就是创建代理:

技术图片

 

 

 技术图片

 

 

技术图片

 

 

 技术图片

 

 

技术图片

 

 

到这里代理对象创建完成。

技术图片

 

 对象已经被代理

技术图片

 

 

所以注册到一级缓存中的对象也是代理对象

 

4:调用某个接口实际上就是调用代理的invoke

技术图片

 

 技术图片

 

 

技术图片

 

 

先调用after的Advice

技术图片

 

 

再调用around的Advice

技术图片

 

 

进入around的切面方法:

技术图片

 

 调到before的Advicefang方法:

技术图片

 

 调用before的切面方法:

技术图片

 

 

然后调到真正的test方法

 

最后调到after的通知方法,在finally代码块中:

技术图片

 

 技术图片

 

 

到这里调用链的调用就结束了。

 

总结:aop的流程主要有一下步骤:

1:注册BeanDefinition,在xml中配置aop自定义标签或者注解开启Enable都会注册动态代理的BeanPostProcessor接口

2:在registryBeanPostProcessor中实例化对象并注册到beanPostProcessors集合中,以备后面使用

3:在预实例化第一个bean的时候就会搜集所有的Aspect切面信息,然后获取切面信息的Advisor,缓存起来

4:拿所有的bean匹配Advisor信息,如果能够匹配上,把Advisor的对象放入放入中返回,如果不为空,则创建该bean的代理对象。

5:当调用该bean的方法时,会调用到横切面上,然后调用链会依次调用链中的放入,对方法进行增强。

 

spring源码分析——Aop的流程

标签:oid   单例对象   link   完成   结果   根据   实现原理   maps   figure   

原文地址:https://www.cnblogs.com/warrior4236/p/13254112.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!