2019独角兽企业重金招聘Python工程师标准>>>

准备示例代码地址

https://github.com/suzhe2018/spring-basic

1、注解@EnableAspectJAutoProxy

@EnableAspectJAutoProxy注解的作用是开启AOP,下面看看该注解做了哪些事情。

通过查看该注解,可以看出它引入了AspectJAutoProxyRegistrar组件。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
   //proxyTargetClass属性,默认false,采用JDK动态代理织入增强(实现接口的方式);如果设为true,则采用CGLIB动态代理织入增强boolean proxyTargetClass() default false;//通过aop框架暴露该代理对象,aopContext能够访问boolean exposeProxy() default false;
}

AspectJAutoProxyRegistrar组件实现了ImportBeanDefinitionRegistrar的接口。这是往spring容器中注册bean的一种方式,详细可以参考我的这篇博客

Spring-bean组件注册(https://my.oschina.net/suzheworld/blog/3008094)。

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {/*** Register, escalate, and configure the AspectJ auto proxy creator based on the value* of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing* {@code @Configuration} class.*/@Overridepublic 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);}}}}

AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);  如果有需要的话,注册AspectJAnnotationAutoProxyCreator

以debug模式进行测试一下。

进入registerAspectJAnnotationAutoProxyCreatorIfNecessary方法

继续跟进,可以看到调用了registerOrEscalateApcAsRequired方法,并把AnnotationAwareAspectJAutoProxyCreator.class作为一个参数传入。

跟进registerOrEscalateApcAsRequired方法

@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry,@Nullable Object source) {Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
//如果registry包含AUTO_PROXY_CREATOR_BEAN_NAME【org.springframework.aop.config.internalAutoProxyCreator】
//这个bean组件,执行内部内容if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);if (!cls.getName().equals(apcDefinition.getBeanClassName())) {int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());int requiredPriority = findPriorityForClass(cls);if (currentPriority < requiredPriority) {apcDefinition.setBeanClassName(cls.getName());}}return null;}
   //如果没有注册internalAutoProxyCreator,则注册internalAutoProxyCreator,//类型为AnnotationAwareAspectJAutoProxyCreator.classRootBeanDefinition beanDefinition = new RootBeanDefinition(cls);beanDefinition.setSource(source);beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);return beanDefinition;
}

可以看到该方法给容器中注册internalAutoProxyCreator组件, 该组件类型为AnnotationAwareAspectJAutoProxyCreator.class

总结:

spring利用@EnableAspectJAutoProxy中的AspectJAutoProxyRegistrar给我们容器中注册一个AnnotationAwareAspectJAutoProxyCreator组件;

翻译过来其实就叫做 ”注解装配模式的ASPECT切面自动代理创建器”组件。

2、AnnotationAwareAspectJAutoProxyCreator

注解@EnableAspectJAutoProxy向容器中注册了AnnotationAwareAspectJAutoProxyCreator组件,剩下的事就交由AnnotationAwareAspectJAutoProxyCreator组件去负责。下面看看AnnotationAwareAspectJAutoProxyCreator类到底有什么特性,可以实现aop的功能。

AnnotationAwareAspectJAutoProxyCreator继承关系图表

从上面的图中,可以看出AnnotationAwareAspectJAutoProxyCreator具备BeanPostProcessor、Aware、Ordered的特性。

下面分析一下,下面这段代码spring做了什么事

AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(AopConfig.class);

首先我们可以看到new对象时通过构造函数传入了配置类。

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {this();
//根据配置类向spring容器中注册bean定义信息。register(annotatedClasses);
//刷新spring容器,完成bean实例的初始化。refresh();
}

下面看看refresh方法

@Override
public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) { //prepareRefresh()刷新前的预处理;prepareRefresh();//获取BeanFactoryConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// BeanFactory的预准备工作prepareBeanFactory(beanFactory);try {// BeanFactory准备工作完成后进行的后置处理工作postProcessBeanFactory(beanFactory);// BeanFactory的后置处理器,两个接口:BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessorinvokeBeanFactoryPostProcessors(beanFactory); // 注册BeanPostProcessor(Bean的后置处理器)【 intercept bean creation】registerBeanPostProcessors(beanFactory);  // 初始化MessageSource组件(做国际化功能;消息绑定,消息解析)initMessageSource(); // 初始化事件派发器;initApplicationEventMulticaster();// 留给子容器(子类)去实现onRefresh();// 从容器中拿到所有的监听器,把他们注册到applicationEventMulticaster中;registerListeners();// 初始化所有剩下的非懒加载的单实例bean;finishBeanFactoryInitialization(beanFactory);//完成BeanFactory的初始化创建工作;IOC容器就创建完成;finishRefresh();}......}
}

refresh方法里有个registerBeanPostProcessors,该方法会注册所有实现了BeanPostProcessor的bean到spring容器中,AnnotationAwareAspectJAutoProxyCreator就是在该方法里完成bean的创建和初始化。

下面打个断点,跟进该方法,看看里面到底做了哪些事。

一路跟进,直到方法registerBeanPostProcessors

下面分析一下该方法到底做了哪些事?

public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
   //先获取ioc容器已经定义了的需要创建对象的所有BeanPostProcessorString[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));// Separate between BeanPostProcessors that implement PriorityOrdered,// Ordered, and the rest.List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();List<String> orderedPostProcessorNames = new ArrayList<>();List<String> nonOrderedPostProcessorNames = new ArrayList<>(); //优先注册实现了PriorityOrdered接口的BeanPostProcessor; for (String ppName : postProcessorNames) {if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);priorityOrderedPostProcessors.add(pp);if (pp instanceof MergedBeanDefinitionPostProcessor) {internalPostProcessors.add(pp);}}else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {orderedPostProcessorNames.add(ppName);}else {nonOrderedPostProcessorNames.add(ppName);}}// First, register the BeanPostProcessors that implement PriorityOrdered.sortPostProcessors(priorityOrderedPostProcessors, beanFactory);registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);// 再给容器中注册实现了Ordered接口的BeanPostProcessor;List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();for (String ppName : orderedPostProcessorNames) {BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);orderedPostProcessors.add(pp);if (pp instanceof MergedBeanDefinitionPostProcessor) {internalPostProcessors.add(pp);}}sortPostProcessors(orderedPostProcessors, beanFactory);registerBeanPostProcessors(beanFactory, orderedPostProcessors); // 注册没实现优先级接口的BeanPostProcessor;List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();for (String ppName : nonOrderedPostProcessorNames) {BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);nonOrderedPostProcessors.add(pp);if (pp instanceof MergedBeanDefinitionPostProcessor) {internalPostProcessors.add(pp);}}registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);// Finally, re-register all internal BeanPostProcessors.sortPostProcessors(internalPostProcessors, beanFactory);registerBeanPostProcessors(beanFactory, internalPostProcessors);// Re-register post-processor for detecting inner beans as ApplicationListeners,// moving it to the end of the processor chain (for picking up proxies etc).beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

注册BeanPostProcessor,实际上就是创建BeanPostProcessor实例,保存在容器中;

debug到下面这行代码,可以看到,调用了beanFactory.getBean方法获取bean实例

跟进getBean方法,可以看到调用了doGetBean方法,一般do开头的方法,都是真正做事的方法。

跟进doGetBean方法,这里用lamda表达式调用了createBean方法去创建bean

进入getSingleton方法

点击下一步直到下面这行代码

跟进这个方法,debug就走到下面这行代码

跟进 createBean方法,一直走到下面这行代码

跟进doCreateBean方法,可以看到该方法所在的类为AbstractAutowireCapableBeanFactory

下面分析一下该方法

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)throws BeanCreationException {// Instantiate the bean.BeanWrapper instanceWrapper = null;if (mbd.isSingleton()) {instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);}if (instanceWrapper == null) {//创建bean实例instanceWrapper = createBeanInstance(beanName, mbd, args);}......// Initialize the bean instance.Object exposedObject = bean;try {//属性赋值populateBean(beanName, mbd, instanceWrapper);//初始化exposedObject = initializeBean(beanName, exposedObject, mbd);}......return exposedObject;
}

以上是创建和注册AnnotationAwareAspectJAutoProxyCreator的过程,其实在spring中每一个bean的实例化,都会经过上面的这个流程

3、业务类加上aop代理

在refresh方法中调用了下面的方法,该方法完成BeanFactory初始化工作;创建剩下的单实例bean

finishBeanFactoryInitialization(beanFactory);

在类AbstractAutoProxyCreator中的postProcessAfterInitialization方法打一个断点。

不断放行,直到类名为BussinessService

向下执行进入wrapIfNecessary方法。

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {.....
 /***获取当前bean的所有增强器(通知方法)  Object[]  specificInterceptors*    1、找到候选的所有的增强器(找哪些通知方法是需要切入当前bean方法的)*    2、获取到能在bean使用的增强器。*    3、给增强器排序*/Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);if (specificInterceptors != DO_NOT_PROXY) {//2.保存当前bean在advisedBeans中;this.advisedBeans.put(cacheKey, Boolean.TRUE);
/* * 如果当前bean需要增强,创建当前bean的代理对象;*             1)、获取所有增强器(通知方法)*             2)、保存到proxyFactory*             3)、创建代理对象:Spring自动决定*                 JdkDynamicAopProxy(config);jdk动态代理;*                 ObjenesisCglibAopProxy(config);cglib的动态代理;
*/Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));this.proxyTypes.put(cacheKey, proxy.getClass()); //返回代理对象return proxy;}this.advisedBeans.put(cacheKey, Boolean.FALSE);return bean;
}

生成的代理对象如下,因为BussinessService没有接口,所以采用了cglib的方式生成代理对象。

点击下面标红的地方

可以看出在初始化方法里执行了applyBeanPostProcessorsAfterInitialization方法。

进入该方法可以看到,spring容器中所有BeanPostProcessor类型的实例bean都会对新创建的bean加工处理一遍。

加工处理后的bean就会存储到spring容器中。

4、目标方法执行

上面介绍了AnnotationAwareAspectJAutoProxyCreator 对BussinessService进行了包装,生成了代理类。下面看一看目标方法是如何调用的。

断点打到下面这个位置。

debug进入doBussiness方法,可以看到DynamicAdvisedInterceptor.intercept();拦截目标方法的执行。

@Override
@Nullable
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {Object oldProxy = null;boolean setProxyContext = false;Object target = null;TargetSource targetSource = this.advised.getTargetSource();try {if (this.advised.exposeProxy) {oldProxy = AopContext.setCurrentProxy(proxy);setProxyContext = true;}target = targetSource.getTarget();Class<?> targetClass = (target != null ? target.getClass() : null); //获取将要执行的目标方法拦截器链;List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);Object retVal;if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);//如果没有拦截器链,直接执行目标方法;retVal = methodProxy.invoke(target, argsToUse);}else {//如果有拦截器链,把需要执行的目标对象,目标方法,拦截器链等信息传入创建一个 CglibMethodInvocation 对象//然后调用proceed()方法retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();}retVal = processReturnType(proxy, target, method, retVal);return retVal;}finally {if (target != null && !targetSource.isStatic()) {targetSource.releaseTarget(target);}if (setProxyContext) {// Restore old proxy.AopContext.setCurrentProxy(oldProxy);}}
}

进入 proceed()方法

@Override
@Nullable
public Object proceed() throws Throwable { // 如不当前拦截器的索引=interceptorsAndDynamicMethodMatchers的长度-1,也即是说如果到了最后一个拦截器,执行目标方法if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {return invokeJoinpoint();}//获取下一个拦截器Object interceptorOrInterceptionAdvice =this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { // 如果是动态切面,需要进行参数匹配,以确定是否需要执行该动态横切逻辑InterceptorAndDynamicMethodMatcher dm =(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {return dm.interceptor.invoke(this);}else { // 动态切面匹配失败,执行链上的下一个拦截器return proceed();}}else {
     //非动态切面直接调用 MethodInterceptor的invoke方法 传入this即ReflectiveMethodInvocation实例 //传入this进入,这样就可以形成一个调用的链条了return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);}
}

因为这里的程序创建的不是动态切面,所以他只会执行else里的逻辑

return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);

可以在这里打个断点

第1次执行ExposeInvocationInterceptor的invoke方法,该方法会调用mi.proceed(),又在一次执行到return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);

第2次拦截器为AspectJAfterThrowingAdvice,该方法同样会调用mi.proceed()方法。如果调用mi.proceed()方法发生了异常,则会执行异常通知方法。

第3次执行AfterReturningAdviceInterceptor里的invoke方法,该方法里也会调用mi.proceed()方法,调用成功后,会执行返回通知方法。

第4次执行AspectJAfterAdvice里的方法,值得注意的是这里执行后置通知方法放在了finally里。所以无论是否发生异常,都会执行。

第5次执行AspectJAroundAdvice里的方法,该方法调用到proceedingJoinPoint.proceed(),又会在一次进入ReflectiveMethodInvocation的proceed()方法。然后会调用最后一个拦截器MethodBeforeAdviceInterceptor,执行前置通知方法。

MethodBeforeAdviceInterceptor方法执行后,会再一次调用mi.proceed(); 此时后面没有拦截器了,目标方法会被执行。

这样不断的调用mi.proceed()方法,直到最后一个拦截器的方法调用完,执行目标方法。通过这种递归调用的方式实现aop各个通知方法的执行。

if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {return invokeJoinpoint();}

转载于:https://my.oschina.net/suzheworld/blog/3009400

spring-aop源码分析相关推荐

  1. Spring AOP 源码分析 - 拦截器链的执行过程

    1.简介 本篇文章是 AOP 源码分析系列文章的最后一篇文章,在前面的两篇文章中,我分别介绍了 Spring AOP 是如何为目标 bean 筛选合适的通知器,以及如何创建代理对象的过程.现在我们的得 ...

  2. Spring AOP 源码分析 - 创建代理对象

    1.简介 在上一篇文章中,我分析了 Spring 是如何为目标 bean 筛选合适的通知器的.现在通知器选好了,接下来就要通过代理的方式将通知器(Advisor)所持有的通知(Advice)织入到 b ...

  3. Spring AOP 源码分析 - 筛选合适的通知器

    1.简介 从本篇文章开始,我将会对 Spring AOP 部分的源码进行分析.本文是 Spring AOP 源码分析系列文章的第二篇,本文主要分析 Spring AOP 是如何为目标 bean 筛选出 ...

  4. spring AOP源码分析(一)

    spring AOP源码分析(一) 对于springAOP的源码分析,我打算分三部分来讲解:1.配置文件的解析,解析为BeanDefination和其他信息然后注册到BeanFactory中:2.为目 ...

  5. 一步一步手绘Spring AOP运行时序图(Spring AOP 源码分析)

    相关内容: 架构师系列内容:架构师学习笔记(持续更新) 一步一步手绘Spring IOC运行时序图一(Spring 核心容器 IOC初始化过程) 一步一步手绘Spring IOC运行时序图二(基于XM ...

  6. 【Spring】Spring AOP源码分析-导读(一)

    文章目录 1.简介 2.AOP 原理 3.AOP 术语及相应的实现 3.1 连接点 - Joinpoint 3.2 切点 - Pointcut 3.3 通知 - Advice 3.4 切面 - Asp ...

  7. Spring AOP源码分析(八)SpringAOP要注意的地方

    2019独角兽企业重金招聘Python工程师标准>>> SpringAOP要注意的地方有很多,下面就举一个,之后想到了再列出来: (1)SpringAOP对于最外层的函数只拦截pub ...

  8. Spring AOP源码分析(七)ProxyFactoryBean介绍

    2019独角兽企业重金招聘Python工程师标准>>> 这篇文章里面就要说说Spring自己的AOP,搞清楚哪种方式是Spring自己实现的AOP,哪种方式是Spring引入aspe ...

  9. Spring AOP源码分析(四)Spring AOP的JDK动态代理

    2019独角兽企业重金招聘Python工程师标准>>> 本篇文章将会介绍上一个例子中的源码执行情况,从中熟悉整个SpringAOP的一些概念和接口设计. 首先整个SpringAOP的 ...

  10. Spring AOP源码分析二

    上一篇中,我们已经找到了AOP的源码入口,我们今天继续分析下面的代码,不过在此之前我们需要看下Spring中如何使用切面的,以便于我们理解我们的源码.代码如下: package com.younger ...

最新文章

  1. 苏炳添招研究生了!上课画面曝光,网友:千万不要逃课……
  2. Java网络编程之TCP、UDP
  3. 表单开发(二):获取单选按钮,多行文本框,下拉菜单,捆绑元素数据,用户注册
  4. 【Lua】LuaForWindows_v5.1.4-46安装失败解决方案
  5. Linuxday01基础命令
  6. 龙图 VP 李翀:数据化运营及云计算下的运维
  7. 教程:用Java创建和验证JWT
  8. java里面value_「Java基础知识」Java中包含哪些运算符
  9. 平台系统云服务器配置,01-云平台连接配置
  10. 前端诸神大战,Vue、React 依旧笑傲江湖
  11. 解决ajax回调函数无返回值得问题
  12. Web API-随机性案例步骤
  13. Redis 介绍2——常见基本类型
  14. python 腾讯视频签到_腾讯视频自动签到脚本.
  15. java字节流字符流复制文件大小不一致及乱码
  16. coupon优惠券 -- CSS样式
  17. NetCore3.1开发后台管理系统框架思路与实现
  18. 《修C传》——初始C语言 <凝气篇>
  19. 《漫画算法》读书笔记
  20. 题9.5:有10个学生,每个学生的数据包括学号、姓名、3门课程的成绩,从键盘输人10个 学生数据,要求输出3门课程总平均成绩,以及最高分的学生的数据(包括学号、姓 名、3门课程成绩、平均分数)。

热门文章

  1. Java内存溢出定位和解决方案(new)
  2. 微信小程序------开发测试
  3. 多线程等待/通知机制
  4. (一二一)核心动画基础
  5. 20130418定义全局变量
  6. PostgreSQL学习手册(三) 表的继承和分区
  7. NET 连接池救生员
  8. NYOJ 822 画图
  9. IOS中常见UI细节和常识
  10. STC12LE5620AD RAM问题