SpringAOP源码跟踪及学习

Spring 版本 4.3.2

在拿到 Bean 实例以后,会经历一系列的初始化工作,如:工厂回调、init 方法、后处理器在 Bean 初始化前后的处理等,在一般情况下(非 factory-method 创建的 Bean 等),AOP代理对象的创建就在后处理器的处理方法中实现。

入口

以 AbstractAutowireCapableBeanFactory 类中的 initializeBean 方法作为起始点进行跟踪

1/** 2* Initialize the given bean instance, applying factory callbacks 3* as well as init methods and bean post processors. 4* <p>Called from {@link #createBean} for traditionally defined beans, 5* and from {@link #initializeBean} for existing bean instances. 6* 7* 初始化给定的 bean 实例,应用工厂回调方法以及 init 方法和 bean 的后处理器。 8* 该方法会被传统定义 bean 的 createBean 方法所调用,也会被重载方法所引用 9*/ 10protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { 11 if (System.getSecurityManager() != null) { 12 AccessController.doPrivileged((PrivilegedAction<Object>) () -> { 13 invokeAwareMethods(beanName, bean); 14 return null; 15 }, getAccessControlContext()); 16 } 17 else { 18 invokeAwareMethods(beanName, bean); 19 } 20 21 Object wrappedBean = bean; 22 if (mbd == null || !mbd.isSynthetic()) { 23 24 // 后处理器的前调用 25 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); 26 } 27 28 try { 29 invokeInitMethods(beanName, wrappedBean, mbd); 30 } 31 catch (Throwable ex) { 32 throw new BeanCreationException( 33 (mbd != null ? mbd.getResourceDescription() : null), 34 beanName, "Invocation of init method failed", ex); 35 } 36 if (mbd == null || !mbd.isSynthetic()) { 37 38 // 初始化后,进行后处理器的后调用,跟踪此方法 39 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); 40 } 41 42 return wrappedBean; 43}

依然在 AbstractAutowireCapableBeanFactory 类中。

拿到 BeanFactory 中所有针对 Bean 的后处理器集合,依次调用。

1public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) 2 throws BeansException { 3 4 Object result = existingBean; 5 for (BeanPostProcessor processor : getBeanPostProcessors()) { 6 7 // 利用处理器的处理方法,对 bean 实例进行处理,并返回一个对象 8 Object current = processor.postProcessAfterInitialization(result, beanName); 9 if (current == null) { 10 return result; 11 } 12 result = current; 13 } 14 return result; 15}

注册创建器

在后处理器集合中,有一个处理器叫做 AnnotationAwareAspectJAutoProxyCreator 创建器,该处理器在解析<aop:config>标签、或者解析相关注解时被注册到工厂中,如下:

1// 如果必要的话注册AspectJ自动代理创建器 2public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) { 3 4 // 传递了 AspectJAwareAdvisorAutoProxyCreator 的 Class,进入这个方法 5 return registerOrEscalateApcAsRequired(AspectJAwareAdvisorAutoProxyCreator.class, registry, source); 6} 7 8 9private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) { 10 Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); 11 12 //工厂中是否已经注册了 org.springframework.aop.config.internalAutoProxyCreator 13 if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) { 14 BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME); 15 16 //如果已经有注册了 internalAutoProxyCreator,并且和入参传递的Class不是同一个Class, 17 //那么就根据优先级进行选择 18 if (!cls.getName().equals(apcDefinition.getBeanClassName())) { 19 20 //类 AopConfigUtils 中有个 ArrayList 属性 APC_PRIORITY_LIST,在类静态构造中依次加入了 21 //几个创建器,这个方法就是查找某个创建器在 APC_PRIORITY_LIST 中的索引,如果没有找到就报错 22 int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName()); 23 int requiredPriority = findPriorityForClass(cls); 24 25 // internalAutoProxyCreator 的索引为0,入参的 AspectJAwareAdvisorAutoProxyCreator 26 // 索引为1,后者要大,所以重新设置下 apcDefinition 的 beanClass 27 if (currentPriority < requiredPriority) { 28 apcDefinition.setBeanClassName(cls.getName()); 29 } 30 } 31 32 //直接返回null 33 return null; 34 } 35 36 // 如果没有注册 internalAutoProxyCreator ,组装一个 Bean Definition,以 37 // AspectJAwareAdvisorAutoProxyCreator 作为 bean Class,然后注册到工厂中 38 RootBeanDefinition beanDefinition = new RootBeanDefinition(cls); 39 beanDefinition.setSource(source); 40 beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE); 41 beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); 42 registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition); 43 return beanDefinition; 44}

从上面可以看见创建器 AnnotationAwareAspectJAutoProxyCreator 的注册经过,Bean Definition 是对 Bean 的描述,创建 bean 对象时,会以 Bean Definition 为依据进行实例化和初始化。

postProcessAfterInitialization

查看创建器的处理方法postProcessAfterInitialization

该方法在创建器的超类 AbstractAutoProxyCreator 中实现

1/** 2* Create a proxy with the configured interceptors if the bean is 3* identified as one to proxy by the subclass. 4* 5* 如果 bean 被定义为子类代理,则使用已配置的拦截器创建代理 6*/ 7@Override 8public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) { 9 if (bean != null) { 10 Object cacheKey = getCacheKey(bean.getClass(), beanName); 11 if (!this.earlyProxyReferences.contains(cacheKey)) { 12 13 // 缓存中没有的情况 14 return wrapIfNecessary(bean, beanName, cacheKey); 15 } 16 } 17 return bean; 18} 19 20/** 21* Wrap the given bean if necessary, i.e. if it is eligible for being proxied. 22* 23* 必要的话包装给定的 bean,即,他有资格被代理 24*/ 25protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { 26 if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) { 27 return bean; 28 } 29 30 // advisedBeans 存放 bean 是否可以被代理的信息,作为缓存,避免重复判断 31 // Map<Object, Boolean> advisedBeans = new ConcurrentHashMap<> 32 if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { 33 return bean; 34 } 35 36 if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { 37 38 // 如果 bean 是一些特殊的类,比如 Pointcut/Advisor,又或者没有 @Aspect 注解等 39 // 这些 bean 不应该被代理,信息存放到 advisedBeans 集合中 40 this.advisedBeans.put(cacheKey, Boolean.FALSE); 41 return bean; 42 } 43 44 // Create proxy if we have advice. 45 // 如果有通知,创建代理 46 47 // 拿到所有匹配该 bean 的通知,如果使用了切入点表达式或者 AspectJ 风格的增强, 48 // 还需要在通知链的开始处添加 ExposeInvocationInterceptor 拦截器 49 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); 50 if (specificInterceptors != DO_NOT_PROXY) { 51 52 // 通知链不为null,可以代理 53 this.advisedBeans.put(cacheKey, Boolean.TRUE); 54 55 // 创建代理对象,进入跟踪 56 Object proxy = createProxy( 57 bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); 58 59 // 存放已经生成代理对象的类信息 60 this.proxyTypes.put(cacheKey, proxy.getClass()); 61 return proxy; 62 } 63 64 this.advisedBeans.put(cacheKey, Boolean.FALSE); 65 return bean; 66}

创建代理

该方法在 AbstractAutoProxyCreator 中实现

1/** 2* Create an AOP proxy for the given bean. 3* 4* 为指定的 bean 创建一个 AOP 代理 5*/ 6protected Object createProxy(Class<?> beanClass, @Nullable String beanName, 7 @Nullable Object[] specificInterceptors, TargetSource targetSource) { 8 9 if (this.beanFactory instanceof ConfigurableListableBeanFactory) { 10 11 // 在 beanFactory 中,beanName 有对应的 BeanDefinition,此方法就是为 BeanDefinition 的 12 // attributes 属性添加键值对,key 为 xxx.originalTargetClass , value 包含了 targetSource 13 AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass); 14 } 15 16 ProxyFactory proxyFactory = new ProxyFactory(); 17 18 // 将创建器中的一些属性拷贝到新创建的代理工厂 19 proxyFactory.copyFrom(this); 20 21 // proxyTargetClass 属性对代理方式的确定有非常大的影响 22 // 当从创建器中拷贝的属性 proxyFactory 为 false 时,下面的两个方法需要详细跟踪 23 if (!proxyFactory.isProxyTargetClass()) { 24 if (shouldProxyTargetClass(beanClass, beanName)) { 25 proxyFactory.setProxyTargetClass(true); 26 } 27 else { 28 evaluateProxyInterfaces(beanClass, proxyFactory); 29 } 30 } 31 32 // 对拦截器或者通知进行包装,包装成Advisor对象 33 Advisor[] advisors = buildAdvisors(beanName, specificInterceptors); 34 35 // 在代理工厂中添加 Advisor 通知链 36 proxyFactory.addAdvisors(advisors); 37 proxyFactory.setTargetSource(targetSource); 38 39 // 子类中如果没有覆盖,那么此方法为空实现 40 customizeProxyFactory(proxyFactory); 41 42 proxyFactory.setFrozen(this.freezeProxy); 43 if (advisorsPreFiltered()) { 44 proxyFactory.setPreFiltered(true); 45 } 46 47 // 通过代理工厂获取代理 48 return proxyFactory.getProxy(getProxyClassLoader()); 49}

proxyTargetClass 布尔属性值的确定对代理方式有着非常大的影响。

当配置了<aop:aspectj-autoproxy>,使用注解方式时;又或者是使用xml配置<aop:config>时,两个标签都具有的proxy-target-class属性默认为 false

那么上述步骤创建 ProxyFactory 对象时,从创建器中拷贝的 proxyTargetClass 属性则为 false,进入条件

1if (!proxyFactory.isProxyTargetClass()) { 2 if (shouldProxyTargetClass(beanClass, beanName)) { 3 proxyFactory.setProxyTargetClass(true); 4 } 5 else { 6 evaluateProxyInterfaces(beanClass, proxyFactory); 7 } 8}

先看第一个方法shouldProxyTargetClass

shouldProxyTargetClass

该方法在 AbstractAutoProxyCreator 中实现

1/** 2* Determine whether the given bean should be proxied with its target class rather than its interfaces. 3* <p>Checks the {@link AutoProxyUtils#PRESERVE_TARGET_CLASS_ATTRIBUTE "preserveTargetClass" attribute} 4* of the corresponding bean definition. 5* 6* 确定给定的bean是否应该使用其目标类而不是其接口进行代理。 7* 检查对应 bean definition 的 preserveTargetClass 属性。 8*/ 9protected boolean shouldProxyTargetClass(Class<?> beanClass, String beanName) { 10 11 return (this.beanFactory instanceof ConfigurableListableBeanFactory && 12 AutoProxyUtils.shouldProxyTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName)); 13 14}

工厂默认实现 DefaultListableBeanFactory 类实现了 ConfigurableListableBeanFactory 接口。

跟踪 AutoProxyUtils 类的 shouldProxyTargetClass 方法。

1public static boolean shouldProxyTargetClass(ConfigurableListableBeanFactory beanFactory, String beanName) { 2 3 // 工厂中有对应 beanName 的 bean definition 则进入条件 4 if (beanName != null && beanFactory.containsBeanDefinition(beanName)) { 5 BeanDefinition bd = beanFactory.getBeanDefinition(beanName); 6 7 // bean definition 的 attributes 属性中是否有 8 // org.springframework.aop.framework.autoproxy.AutoProxyUtils.preserveTargetClass 9 // 为 key 的属性,且 value 为 ture 10 return Boolean.TRUE.equals(bd.getAttribute(PRESERVE_TARGET_CLASS_ATTRIBUTE)); 11 } 12 return false; 13}

如果被代理 bean 对应的 bean definition 属性中,存在org.springframework.aop.framework.autoproxy.AutoProxyUtils.preserveTargetClass为 key,且 值为 true 的 attributes

那么设置 proxyTargetClass 为 ture

再看第二个方法

evaluateProxyInterfaces

该方法在类 ProxyProcessorSupport 中实现,ProxyProcessorSupport 是 AbstractAutoProxyCreator 的父类

1/** 2* Check the interfaces on the given bean class and apply them to the {@link ProxyFactory}, 3* if appropriate. 4* <p>Calls {@link #isConfigurationCallbackInterface} and {@link #isInternalLanguageInterface} 5* to filter for reasonable proxy interfaces, falling back to a target-class proxy otherwise. 6* 7* 检查指定 bean class 上的接口,如果合适的话设置到 ProxyFactory 中。 8* 调用 isConfigurationCallbackInterface 方法和 isInternalLanguageInterface 方法去过滤得到 9* 合理的代理接口,否则回退到 target-class proxy 10*/ 11protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) { 12 13 // 此方法拿到类上及其父类上,所有的接口,不会递归获取接口上的接口 14 Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader()); 15 boolean hasReasonableProxyInterface = false; 16 17 // 遍历所有的接口,并进行过滤 18 for (Class<?> ifc : targetInterfaces) { 19 20 // 接口中不能有像 Aware、InitializingBean 等容器的回调接口 21 // 接口的 ClassName 也不能是以 .cglib.proxy.Factory 结尾或者是 groovy.lang.GroovyObject 22 // 这样的内部语言接口 23 if (!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) && 24 ifc.getMethods().length > 0) { 25 26 // 如果还有接口剩余,则存在合适的代理接口 27 hasReasonableProxyInterface = true; 28 break; 29 } 30 } 31 if (hasReasonableProxyInterface) { 32 33 // 将代理接口一个个添加到 proxyFactory 中 34 for (Class<?> ifc : targetInterfaces) { 35 proxyFactory.addInterface(ifc); 36 } 37 } 38 else { 39 40 // 否者 proxyTargetClass 属性设置为 true 41 proxyFactory.setProxyTargetClass(true); 42 } 43}

总结一下两个方法

当 xml 中没有配置 proxyTargetClass 属性,默认为 false

如果被代理 bean 对应的 bean definition ,它的 attributes 属性中,存在org.springframework.aop.framework.autoproxy.AutoProxyUtils.preserveTargetClass为 key,值为 true 的键值对

那么设置 proxyTargetClass 为 ture

否则过滤所有接口,接口不能为 Aware、InitializingBean 等容器的回调接口,也不能是内部语言接口

如果没有合适的接口,proxyTargetClass 还是设置为 true 。

接下来看下代理工厂获取代理的流程。

getProxy

进入 ProxyFactory 类中,跟踪 getProxy 方法

1/** 2* Create a new proxy according to the settings in this factory. 3* <p>Can be called repeatedly. Effect will vary if we've added 4* or removed interfaces. Can add and remove interceptors. 5* <p>Uses the given class loader (if necessary for proxy creation). 6* 7* 根据这个 factory 的设置创建一个新的代理。 8* 可以被重复调用。如果我们添加或者移除了接口,会有影响。 9* 可以添加和移除拦截器。 10* 使用指定的类加载器(如果需要代理创建) 11*/ 12public Object getProxy(@Nullable ClassLoader classLoader) { 13 return createAopProxy().getProxy(classLoader); 14}

先跟踪 createAopProxy 方法,此方法在 ProxyCreatorSupport 类中实现,ProxyFactory 是其子类。

1/** 2* Subclasses should call this to get a new AOP proxy. They should <b>not</b> 3* create an AOP proxy with {@code this} as an argument. 4* 5* 子类应该调用这个方法去获得一个新的AOP代理。他们不应该用 this 作为参数创建一个AOP代理 6*/ 7protected final synchronized AopProxy createAopProxy() { 8 9 // 当AOP代理第一次被创建时,active会被设置为true 10 if (!this.active) { 11 12 // 设置 active 为 true,激活代理配置 13 activate(); 14 } 15 return getAopProxyFactory().createAopProxy(this); 16}

getAopProxyFactory 方法拿到的是 DefaultAopProxyFactory 的实例,它的接口是 AopProxyFactory

ProxyFactory 类间接继承 AdvisedSupport ,AdvisedSupport 继承 ProxyConfig ,作为配置存在

ProxyFactory 类和 DefaultAopProxyFactory 并没有继承关系

以 ProxyFactory 类的实例为参数,调用 createAopProxy 方法,继续跟踪

createAopProxy

此方法在 DefaultAopProxyFactory 类中实现,采用 JDK proxy 代理还是使用 cglib 代理,在这个方法中决定

1public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { 2 if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { 3 Class<?> targetClass = config.getTargetClass(); 4 if (targetClass == null) { 5 throw new AopConfigException("TargetSource cannot determine target class: " + 6 "Either an interface or a target is required for proxy creation."); 7 } 8 if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { 9 return new JdkDynamicAopProxy(config); 10 } 11 return new ObjenesisCglibAopProxy(config); 12 } 13 else { 14 return new JdkDynamicAopProxy(config); 15 } 16} 17

isOptimize 方法就是返回 ProxyFactory 的 optimize 属性,为布尔值

是否执行积极优化的含义。

优化通常意味着,在代理创建后,通知的变化不会带来影响,默认下为 false。

optimize 在此处也被作为了一个判断依据。

optimize 可以参考文章:https://blog.csdn.net/zh199609/article/details/79710846

isProxyTargetClass 方法拿的则是 ProxyFactory 的 proxyTargetClass 属性,前面已经跟踪过。

hasNoUserSuppliedProxyInterfaces 方法在代理接口不存在,或者只有一个且是 SpringProxy 接口的子接口情况下,才返回 true 。

当上述三个方法都返回 false 时,代理才走的 JDK proxy 代理,也就是接口代理。

当满足其中一个条件,进入方法后,还有一层筛选,要么 target Class 是一个接口,要么是 Proxy 类的子类,否则其余情况都使用 cglib 代理,也就是类代理。

最后调用代理的 getProxy 方法。不同代理的实现,其实就是spring对 JDK 的 Proxy,或者 cglib 的 Enhancer 的封装。最终完成AOP的实现。

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )