基于最新Spring 5.x,介绍了Spring AOP中的AspectJAwareAdvisorAutoProxyCreator自动代理创建者的工作流程,对于创建代理对象的源码进行了深度分析!
前一篇文章Spring AOP源码(1)—<aop:config/>AOP配置标签解析,我们讲解了<aop:config/>标签的解析过程.当前全部标签解析完毕,仅仅是向容器中注册了一些bean定义,还没有进行真正的代理操作,真正创建代理对象操作实际上是在自动代理创建者内部完成的!
在解析的时候就说过,如果具有< aop:config/>标签,没有< aop:aspectj-autoproxy/>以及@EnableAspectJAutoProxy注解,那么最终会在解析标签的时候创建AspectJAwareAdvisorAutoProxyCreator类型的自动代理创建者。
我们先来看看基于XML的< aop:config/>标签的AspectJAwareAdvisorAutoProxyCreator这个自动代理创建者的工作原理,后面再学习其他的自动代理创建者的工作原理,它们都是大同小异的,自动代理创建者用于创建代理对象!
Spring AOP源码(1)—<aop:config/>AOP配置标签解析
Spring AOP源码(2)—AspectJAwareAdvisorAutoProxyCreator创建代理对象
Spring AOP源码(3)—invoke代理方法的调用与执行增强
Spring AOP源码(4)—基于注解的AOP源码解析以及AnnotationAwareAspectJAutoProxyCreator
Spring AOP源码(5)—DefaultAdvisorAutoProxyCreator自动代理创建者
AspectJAwareAdvisorAutoProxyCreator是在解析< aop:config/>AOP标签时注册的一个bean定义,专门用于创建代理对象,实现AOP的核心功能!
AspectJAwareAdvisorAutoProxyCreator的uml类图如下:
一些重要的类如下:
一些重要的回调扩展接口的实现如下:
上面这些的接口,是Spring具有良好扩展性的根本原因之一,我们自己也可以定义对应的扩展接口实现自己的某些逻辑。这些扩展接口的不同回调方法,会在整个IoC容器初始化的过程中,被固定顺序的自动调用,我们在IoC容器初始化(7)的文章末尾已经使用图片展示过了调用顺序,在此不再赘述!
由于AspectJAwareAdvisorAutoProxyCreator属于BeanPostProcessor,那么这个bean定义将会在IoC容器初始化的refresh方法中的registerBeanPostProcessors方法中被实例化并注册,这时虽然所有的bean定义都被加载了,但所有的普通bean定义并没有创建,AspectJAwareAdvisorAutoProxyCreator将会在随后的普通bean 实例创建的过程中发挥重要作用!
这些回调方法中,最重要的就是postProcessBeforeInstantiation和postProcessAfterInitialization方法:
我们下面围绕postProcessBeforeInstantiation和postProcessAfterInitialization这两个回调方法讲解。
postProcessBeforeInstantiation方法在Spring实例化bean之前调用,给一个返回代理对象来代替创建目标bean实例的机会。如果返回值不为null,随后直接执行postProcessAfterInitialization扩展点方法,不会走Spring的实例化、初始化bean的逻辑。否则会走Spring创建对象的逻辑,最后同样会执行postProcessAfterInitialization扩展点方法。
该方法是在父类AbstractAutoProxyCreator的实现中,主要有几个目的和逻辑:
/**
* 通过自定义TargetSourceCreator创建TargetSource的beanName集合
*/
private final Set<String> targetSourcedBeans = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
/**
* 通知的bean缓存,包括AOP基础框架Bean或者免代理的Bean,比如Advisor
*/
private final Map<Object, Boolean> advisedBeans = new ConcurrentHashMap<>(256);
/**
* 代理类型缓存
*/
private final Map<Object, Class<?>> proxyTypes = new ConcurrentHashMap<>(16);
/**
* AbstractAutoProxyCreator的方法
*
* 在bean在Spring实例化bean之前调用,给一个返回代理对象来代替创建目标bean实例的机会。
* 如果返回值不为null,那么通过此扩展点获取的bean,随后还会执行postProcessAfterInitialization扩展点方法,
* 之后直接返回该bean作为实例,否则继续向后调用,通过Spring的规则实例化、初始化bean。
*/
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
//为给定beanClass和beanName生成缓存key
Object cacheKey = getCacheKey(beanClass, beanName);
//如果没设置beanName,或者targetSourcedBeans缓存不包含该beanName
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
//如果advisedBeans缓存包含该beanName,表示已经被处理了,返回null
if (this.advisedBeans.containsKey(cacheKey)) {
//返回null,表示会走Spring创建对象的逻辑,但是后面的postProcessAfterInitialization方法中不会再创建代理
return null;
}
//如果当前bean是Spring AOP的基础结构类,或者shouldSkip返回true,表示不需要代理
//这个shouldSkip方法,在AspectJAwareAdvisorAutoProxyCreator子类中将会被重写并初始化全部的Advisor通知器实例
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
//那么当前cacheKey和value=false存入advisedBeans缓存,表示已处理过并且无需代理
this.advisedBeans.put(cacheKey, Boolean.FALSE);
//返回null,表示会走Spring创建对象的逻辑,但是后面的postProcessAfterInitialization方法中不会再创建代理
return null;
}
}
//如果我们有自定义的TargetSource,那么目标bean没必要通过Spring的机制实例化
//而是使用自定义的TargetSource将以自定义方式实例化目标实例,进而在此处创建代理对象
//根据beanClass和beanClass获取对应的自定义TargetSource
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
//如果获取到了自定义目标源,那么需要再当前方法创建代理
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
//加入targetSourcedBeans缓存集合,表示已处理过,后面的postProcessAfterInitialization方法中不会再创建代理
this.targetSourcedBeans.add(beanName);
}
/*
* 下面就是创建代理的逻辑,这部分我们在下面再讲解
*/
//获取当前bean的Advisor通知器
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
//创建代理对象
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
//将当前cacheKey和代理对象class存入proxyTypes缓存中
this.proxyTypes.put(cacheKey, proxy.getClass());
//返回代理对象,后续不会走Spring创建对象的逻辑
return proxy;
}
//返回null,表示会走Spring创建对象的逻辑
return null;
}
获取缓存的key,如果具有beanName,如果是FactoryBean则返回"&beanName"作为cacheKey,否则直接返回beanName作为cacheKey;如果没有beanName,则直接返回beanClass作为cacheKey。
/**
* BeanFactory接口的属性
* FactoryBean的区分前缀
*/
String FACTORY_BEAN_PREFIX = "&";
/**
* AbstractAutoProxyCreator的方法
*
* 如果具有beanName,如果是FactoryBean则返回"&beanName"作为cacheKey,否则直接返回beanName作为cacheKey
* 如果没有beanName,则直接返回beanClass作为cacheKey
*/
protected Object getCacheKey(Class<?> beanClass, @Nullable String beanName) {
//如果有beanName
if (StringUtils.hasLength(beanName)) {
return (FactoryBean.class.isAssignableFrom(beanClass) ?
BeanFactory.FACTORY_BEAN_PREFIX + beanName : beanName);
} else {
return beanClass;
}
}
如果当前beanClass是Spring AOP的基础结构类,则isInfrastructureClass返回true,不进行代理。默认实现是将Advice、Pointcut、Advisor、AopInfrastructureBean接口及其实现均作为AOP基础结构类。
/**
* AbstractAutoProxyCreator的方法
*
* 判断给定的 bean 类是否表示不应被代理的Spring AOP的基础结构类
* 默认实现是将Advice、Pointcut、Advisor、AopInfrastructureBean及其实现均作为基础结构类,不会被代理
*/
protected boolean isInfrastructureClass(Class<?> beanClass) {
//如果属于Advice、Pointcut、Advisor、AopInfrastructureBean类型之一,那么返回true
boolean retVal = Advice.class.isAssignableFrom(beanClass) ||
Pointcut.class.isAssignableFrom(beanClass) ||
Advisor.class.isAssignableFrom(beanClass) ||
AopInfrastructureBean.class.isAssignableFrom(beanClass);
if (retVal && logger.isTraceEnabled()) {
logger.trace("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]");
}
return retVal;
}
判断是否需要跳过对给定bean进行的自动代理,如果不应考虑对给定bean由此后处理器进行自动代理,则子类应重写此方法以返回 true。
该方法在父类AbstractAutoProxyCreator中的逻辑是:如果beanName以beanCassName开头,并且以“.ORIGINAL”结束,那么返回true,否则返回false。
AspectJAwareAdvisorAutoProxyCreator子类重写了该方法,将会通过findCandidateAdvisors方法查找beanFactory中的所有Advisor类型的通知器bean定义并且初始化(这个方法在其他地方也会调用),如果存在AspectJPointcutAdvisor类型的通知器实例,并且beanName等于aspectName,即表示当前的bean属于这个通知器的切面方法类bean,那么不应该拦截切面方法类的方法,直接返回true,表示跳过。否则在最后会才会调用父类的逻辑。
在前文中解析< aop:config/>标签时,< aop:advisor/>标签的DefaultBeanFactoryPointcutAdvisor,< aop:declare-parents/>标签的DeclareParentsAdvisor,通知标签的AspectJPointcutAdvisor,它们都属于Advisor,也就是通知器,通常一个切入点和一个通知方法就组成通知器。
另外,如果是AnnotationAwareAspectJAutoProxyCreator类型的自动代理创建者,还会初始化所有基于注解的通知器。
/**
* AspectJAwareAdvisorAutoProxyCreator重写的方法
*
* 是否需要跳过对给定的bean进行自动代理
* 如果不应考虑对给定bean由此后处理器进行自动代理,则子类应重写此方法以返回 true。
*/
@Override
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
// TODO: Consider optimization by caching the list of the aspect names
/*
* 查找bean工厂的所有Advisor类型的通知器bean定义并且初始化,返回Advisor实例的集合。在解析 标签时,
* 标签的DefaultBeanFactoryPointcutAdvisor, 标签的DeclareParentsAdvisor,
* 通知标签的AspectJPointcutAdvisor,他们都属于Advisor,也就是通知器,通常一个切入点和一个通知方法就组成通知器
*/
List<Advisor> candidateAdvisors = findCandidateAdvisors();
/*
* 如果存在AspectJPointcutAdvisor类型的通知器实例,并且当前的bean属于这个通知器的切面方法类bean
* 那么不应该拦截切面方法类的方法,直接返回true,表示跳过
*/
for (Advisor advisor : candidateAdvisors) {
if (advisor instanceof AspectJPointcutAdvisor &&
((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
return true;
}
}
//否则调用父类AbstractAutoProxyCreator的方法
return super.shouldSkip(beanClass, beanName);
}
/**
* AbstractAutoProxyCreator的方法
*
* 是否需要跳过对给定的bean进行自动代理
*/
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
return AutoProxyUtils.isOriginalInstance(beanName, beanClass);
}
/**
* AutowireCapableBeanFactory的属性,初始化现有 bean 实例时"原始实例"约定的后缀
* 追加到完全限定的 beanName之后,例如"com.mypackage.myClass.原始",以便强制要返回的给定实例,即没有代理
*/
String ORIGINAL_INSTANCE_SUFFIX = ".ORIGINAL";
/**
* AutoProxyUtils的方法
*
* 根据".ORIGINAL"确定给定的 bean 名称是否指示"original instance",如果是,那么跳过对它的任何代理
*/
static boolean isOriginalInstance(String beanName, Class<?> beanClass) {
//如果没有设置beanName,或者beanName长度不等于(beanCassName的长度+".ORIGINAL"的长度)
//那么返回false,表示不跳过
if (!StringUtils.hasLength(beanName) || beanName.length() !=
beanClass.getName().length() + AutowireCapableBeanFactory.ORIGINAL_INSTANCE_SUFFIX.length()) {
return false;
}
//如果beanName以beanCassName开始,并且以.ORIGINAL结束,那么返回true,否则返回false
return (beanName.startsWith(beanClass.getName()) &&
beanName.endsWith(AutowireCapableBeanFactory.ORIGINAL_INSTANCE_SUFFIX));
}
获取当前bean的自定义目标源TargetSource。如果获取到了TargetSource,那么将会直接在postProcessBeforeInstantiation方法中创建代理,避免没必要的Spring初始化和实例化流程,同时后面的postProcessAfterInitialization方法中不会再创建代理对象。
每个代理对象保存了一个TargetSource对象,这个TargetSource对象内部封装了一个AOP的目标对象也就是被代理对象,通过getTarget方法可获取目标对象,然后就能通过目标对象调用被代理的原始方法了。如果我们配置没有某个类型的TargetSource(普通类默认都没有配置),那么这个目标对象将通过Spring来初始化,并且将采用默认的SingletonTargetSource目标源,而如果我们此前就自定义了TargetSource,那么就不必走Spring来初始化bean的逻辑了,就是这个道理!
这个TargetSource,即实际上我们在IoC容器初始化(6)的文章中的@Lazy注解的解析中就见过了,它用于解决构造器循环依赖。
//------------AbstractAutoProxyCreator的相关属性--------------
/**
* 自定义的TargetSourceCreator数组
* 通过setCustomTargetSourceCreators方法初始化,默认为null
*/
@Nullable
private TargetSourceCreator[] customTargetSourceCreators;
/**
* bean工厂,通过BeanFactoryAware回调设置
*/
@Nullable
private BeanFactory beanFactory;
/**
* AbstractAutoProxyCreator的方法
*
* 如果设置了任何TargetSourceCreator,则为当前bean尝试创建一个目标源,否则返回null
*
* 此方法实现使用"customTargetSourceCreators"属性,子类可以重写此方法以使用不同的机制。
*
* @param beanClass 创建目标源的beanClass
* @param beanName beanName
* @return 当前bean的目标前
*/
@Nullable
protected TargetSource getCustomTargetSource(Class<?> beanClass, String beanName) {
// 如果customTargetSourceCreators不为null并且当前beanFactory中包含给定的beanName的bean实例或者bean定义
if (this.customTargetSourceCreators != null &&
this.beanFactory != null && this.beanFactory.containsBean(beanName)) {
//遍历全部TargetSourceCreator
for (TargetSourceCreator tsc : this.customTargetSourceCreators) {
//依次调用getTargetSource方法
TargetSource ts = tsc.getTargetSource(beanClass, beanName);
//如果当前TargetSourceCreator的getTargetSource方法的返回的ts不为null,那么就结束遍历,返回ts
if (ts != null) {
// Found a matching TargetSource.
if (logger.isTraceEnabled()) {
logger.trace("TargetSourceCreator [" + tsc +
"] found custom TargetSource for bean with name '" + beanName + "'");
}
return ts;
}
}
}
//未找到自定义目标源,返回null
return null;
}
该回调方法,在bean已实例化、初始化完毕,并且initMethod方法调用完毕之后回调(在Spring的规则之下),或者在前面的postProcessBeforeInstantiation方法的返回值不为null时回调。
该方法是在父类AbstractAutoProxyCreator中实现的,可以对已创建的原始bean实例进行进一步改造和包装,大部分的代理对象的创建也都在该方法中完成的,因此这个方法可以说是Spring AOP的核心方法,之前的方法则可以不用深究。
/**
* AbstractAutoProxyCreator的属性
* 早期代理引用缓存,key为缓存key,value为bean实例
*/
private final Map<Object, Object> earlyProxyReferences = new ConcurrentHashMap<>(16);
/**
* AbstractAutoProxyCreator的方法
*
* 如果 bean 被子类标识为要代理的 bean,则使用配置的拦截器创建代理对象
*
* @param bean 目标bean实例
* @param beanName beanName
* @return 原属对象或者代理对象
*/
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
//获取缓存key,我们在前面的postProcessBeforeInstantiation已经讲过了
Object cacheKey = getCacheKey(bean.getClass(), beanName);
/*
* 如果earlyProxyReferences的缓存移除该cacheKey之后的value不等于当前bean,表示当前bean可能需要被代理
* earlyProxyReferences的数据是在getEarlyBeanReference方法被调用的时候存入进去的
*
* 如果相等,表示此前已经对这个bean已经在getEarlyBeanReference方法中调用过了wrapIfNecessary方法
* 这个判断就是为了保证对同一个bean的同一次创建过程中,wrapIfNecessary方法只被调用一次
*/
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
/*
* 调用wrapIfNecessary方法,如有必要,对目标对象进行代理包装
*/
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
这里的earlyProxyReferences的数据是在getEarlyBeanReference方法被调用的时候存入进去的,如果相等,表示此前已经对这个bean已经在getEarlyBeanReference方法中调用过了wrapIfNecessary方法,这个判断就是为了保证对同一个bean的同一次创建过程中,wrapIfNecessary方法只被调用一次。
getEarlyBeanReference方法用于获取早期bean的实例,此时bean实例还没有被初始化,该方法用于解决循环引用问题,在我们学习"IoC容器初始化(7)"的文章中就说过该方法,默认情况下其他后处理器在该方法是一个空实现,但是现在增加了AOP功能之后新添加了一个AbstractAutoProxyCreator后处理器,它就重写了getEarlyBeanReference方法,用于创建代理对象:
/**
* AbstractAutoProxyCreator的方法
*
* 用于获取早期bean的实例,此时bean实例还没有被初始化,该方法用于解决循环引用问题并尝试创建代理对象
*
* 在我们学习"IoC容器初始化(7)"的文章中就说过该方法,默认情况下其他后处理器在该方法是一个空实现,但是现在增加了AOP功能之后
* 新添加了一个AbstractAutoProxyCreator后处理器,它的getEarlyBeanReference方法则用于创建代理对象
*
* @param bean 已创建的bean实例
* @param beanName beanName
* @return 原始bean实例或者代理对象
*/
@Override
public Object getEarlyBeanReference(Object bean, String beanName) {
//获取缓存key,我们在前面的postProcessBeforeInstantiation已经讲过了
Object cacheKey = getCacheKey(bean.getClass(), beanName);
//这里将缓存key和当前bean实例存入earlyProxyReferences缓存中
this.earlyProxyReferences.put(cacheKey, bean);
//随后调用同一个wrapIfNecessary方法尝试获取代理对象获取还是返回原始对象
return wrapIfNecessary(bean, beanName, cacheKey);
}
如果当前bean对象有资格被代理,那么包装给定的bean类,创建并返回代理对象。
两个核心方法就是getAdvicesAndAdvisorsForBean,获取当前bean可用的Advisor通知器调用链集合;另一个就是createProxy,使用默认的SingletonTargetSource包装目标对象,并且通过JDK或者CGLIB创建代理对象。
//---------AbstractAutoProxyCreator的相关属性----------
/**
* 通过自定义TargetSourceCreator创建TargetSource的beanName集合
*/
private final Set<String> targetSourcedBeans = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
/**
* 通知的bean缓存,包括AOP基础框架Bean或者免代理的Bean,比如Advisor
*/
private final Map<Object, Boolean> advisedBeans = new ConcurrentHashMap<>(256);
/**
* 代理类型缓存
*/
private final Map<Object, Class<?>> proxyTypes = new ConcurrentHashMap<>(16);
/**
* 表示"不进行代理"的返回值便捷常量
*/
@Nullable
protected static final Object[] DO_NOT_PROXY = null;
/**
* AbstractAutoProxyCreator的方法
*
* 如果当前bean对象有资格被代理,那么包装给定的bean类,返回代理对象
*
* @param bean 原始bean实例
* @param beanName beanName
* @param cacheKey 缓存key
* @return 包装bean的代理,或者原始bean实例
*/
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
/*
* 如果targetSourcedBeans缓存中包含该beanName,表示已通过TargetSource创建了代理,直接返回原始bean实例
* targetSourcedBeans在postProcessBeforeInstantiation中就见过了
*/
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
/*
* 如果advisedBeans缓存中包含该cacheKey,并且value为false,表示不需要代理,直接返回原始bean实例
* advisedBeans在postProcessBeforeInstantiation中就见过了
*/
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
/*
* 如果当前bean是Spring AOP的基础结构类,或者shouldSkip返回true,表示不需要代理,直接返回原始bean实例
* 这个shouldSkip方法,在AspectJAwareAdvisorAutoProxyCreator子类中将会被重写并初始化全部的Advisor通知器实例
* 这两个方法在postProcessBeforeInstantiation中就见过了
*/
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
/*
* 类似于postProcessBeforeInstantiation中创建代理的逻辑
* 尝试创建代理对象
*/
/*
* 1 获取当前bean可用的Advisor通知器,该方法由子类实现
*/
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
//如果具有Advisor,那么才可以创建代理
if (specificInterceptors != DO_NOT_PROXY) {
//存入已代理的缓存集合,value=true,表示已创建代理
this.advisedBeans.put(cacheKey, Boolean.TRUE);
/*
* 2 通过JDK或者CGLIB创建代理对象,使用默认的SingletonTargetSource包装目标对象
*/
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
//将当前cacheKey和代理对象class存入proxyTypes缓存中
this.proxyTypes.put(cacheKey, proxy.getClass());
//返回代理对象
return proxy;
}
//最终,存入已代理的缓存集合,value=false,表示不需要创建代理,直接返回原始bean实例
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
获取当前bean可用的Advisor通知器,该方法由子类实现。在解析< aop:config/>标签时,< aop:advisor/>标签的DefaultBeanFactoryPointcutAdvisor,< aop:declare-parents/>标签的DeclareParentsAdvisor,通知标签的AspectJPointcutAdvisor,他们都属于Advisor类型,也就是通知器,通常一个切入点和一个通知方法就组成通知器。
可以看到,内部委托的findEligibleAdvisors方法进行查找,如果返回空集合,那么最终返回null。
/**
1. AbstractAdvisorAutoProxyCreator的方法
2.
3. 返回给定的bean要应用的代理拦截器数组
4. 5. @param beanClass beanClass
6. @param beanName beanName
7. @param targetSource 目标源,这个参数目前没用到
8. @return 返回给定的bean要应用的代理拦截器数组,或者一个空数组,表示只有常见拦截器,或者null,表示不需要代理
*/
@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
/*
* 查找自动代理此类的所有符合条件的Advisors通知器集合
*/
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
//如果是空集合,那么返回null
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
//返回数组
return advisors.toArray();
}
findEligibleAdvisors方法就是核心方法,大概分为四步:
/**
* AbstractAdvisorAutoProxyCreator的方法
*
* 查找自动代理此类的所有符合条件的Advisors通知器集合
*
* @param beanClass 查找通知器的beanClass
* @param beanName 当前代理的beanName
* @return 自动代理此类的所有符合条件的Advisors通知器集合,如果没有切入点或拦截器,将返回空列表,而不是null
*/
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
/*
* 1 查找所有候选Advisors链
* 子类AnnotationAwareAspectJAutoProxyCreator重写了该方法
*/
List<Advisor> candidateAdvisors = findCandidateAdvisors();
/*
* 2 查找可以自动代理此类的所有符合条件的Advisors链
*/
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
/*
* 3 扩展Advisors链的钩子方法,子类可重写该方法添加新的Advisor,或者对已存在的Advisor进行操作
*
* 子类AspectJAwareAdvisorAutoProxyCreator重写了该方法
*/
extendAdvisors(eligibleAdvisors);
/*
* 4 对于Advisors链进行排序,保证调用顺序
* AbstractAdvisorAutoProxyCreator默认采用的是AnnotationAwareOrderComparator比较器
* 该比较器支持Ordered、PriorityOrdered接口,以及@Order、@Priority注解的排序
* 排序规则是order值越小排序越靠前,优先级越高,没有order值则默认排在尾部,优先级最低
* 随后会对不同类型的通知进行特殊排序
*
* 子类AspectJAwareAdvisorAutoProxyCreator重写了该方法,子类AnnotationAwareAspectJAutoProxyCreator也会调用重写的方法
* 使用AspectJPrecedenceComparator比较器进行排序
*/
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
//返回eligibleAdvisors
return eligibleAdvisors;
}
该方法查找候选Advisors,内部是通过advisorRetrievalHelper的findAdvisorBeans方法查找的,advisorRetrievalHelper是Advisor辅助检索器,在BeanFactoryAware接口回调的时候被初始化,类型为BeanFactoryAdvisorRetrievalHelperAdapter。
/**
* AbstractAdvisorAutoProxyCreator的属性
* Advisor辅助检索器,在BeanFactoryAware接口回调的时候被初始化
* 类型为BeanFactoryAdvisorRetrievalHelperAdapter
*/
@Nullable
private BeanFactoryAdvisorRetrievalHelper advisorRetrievalHelper;
/**
* AbstractAdvisorAutoProxyCreator的方法
*
* 查找用于自动代理的所有候选Advisors集合
*
* @return the List of candidate Advisors
*/
protected List<Advisor> findCandidateAdvisors() {
Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
//通过advisorRetrievalHelper的findAdvisorBeans查找
return this.advisorRetrievalHelper.findAdvisorBeans();
}
findAdvisorBeans方法查找候选Advisors,实际上就是将beanFactory中全部的Advisor类型的bean定义找到并构建实例,随后返回即可。
核心方法就是beanNamesForTypeIncludingAncestors和getBean方法,而这两个方法我们在此前IoC容器初始化的系列文章中已经讲过了,在此不再赘述!
//----------BeanFactoryAdvisorRetrievalHelper的相关属性
/**
* bean工厂,在构造器中被初始化
*/
private final ConfigurableListableBeanFactory beanFactory;
/**
* 缓存的已找到的Advisor的beanName数组
*/
@Nullable
private volatile String[] cachedAdvisorBeanNames;
/**
* BeanFactoryAdvisorRetrievalHelper的方法
*
* 查找并初始化当前beanFactory中所有符合条件的 Advisor bean,忽略FactoryBean并排除当前正在创建中的bean
*
* @return Advisor的bean实例集合
*/
public List<Advisor> findAdvisorBeans() {
//获取已找到的Advisor的beanName数组
String[] advisorNames = this.cachedAdvisorBeanNames;
//如果为null,表示没有缓存
if (advisorNames == null) {
/*
* 获取全部Advisor类型的beanName数组
* 这个方法我们在"IoC容器初始化(6)"的文章中已经讲过了
*/
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
//赋值给cachedAdvisorBeanNames,缓存起来,下次直接从缓存获取
this.cachedAdvisorBeanNames = advisorNames;
}
//如果bean工厂中没有任何的Advisor,那么直接返回空集合
if (advisorNames.length == 0) {
return new ArrayList<>();
}
//advisors用于保存找到的Advisor
List<Advisor> advisors = new ArrayList<>();
//遍历advisorNames数组
for (String name : advisorNames) {
/*
* 根据通知器的beanName判断通知器bean是否合格,如果合格才能算作候选Advisor。
* 该方法在BeanFactoryAdvisorRetrievalHelper中默认返回true,被子类BeanFactoryAdvisorRetrievalHelperAdapter重写,
* 继而调用AbstractAdvisorAutoProxyCreator的isEligibleAdvisorBean方法判断,AbstractAdvisorAutoProxyCreator的isEligibleAdvisorBean方法同样默认返回true
*
* isEligibleAdvisorBean被子类DefaultAdvisorAutoProxyCreator和InfrastructureAdvisorAutoProxyCreator重写
* 而AspectJAwareAdvisorAutoProxyCreator和AnnotationAwareAspectJAutoProxyCreator则没有重写
*
* 因此该方法主要是AspectJAwareAdvisorAutoProxyCreator和AnnotationAwareAspectJAutoProxyCreator这两个自动代理创建者会用到
* 而AspectJAwareAdvisorAutoProxyCreator和AnnotationAwareAspectJAutoProxyCreator这两个自动代理创建者默认始终返回true
*/
if (isEligibleBean(name)) {
//当前切面bean是否正在创建中,如果是,那么跳过
if (this.beanFactory.isCurrentlyInCreation(name)) {
if (logger.isTraceEnabled()) {
logger.trace("Skipping currently created advisor '" + name + "'");
}
} else {
try {
/*
* 通过beanFactory.getBean方法初始化这个切面bean,加入advisors集合中
* getBean方法是IoC容器初始化的核心方法,我们在前面的文章中已花费了大量时间讲解
*/
advisors.add(this.beanFactory.getBean(name, Advisor.class));
} catch (BeanCreationException ex) {
Throwable rootCause = ex.getMostSpecificCause();
if (rootCause instanceof BeanCurrentlyInCreationException) {
BeanCreationException bce = (BeanCreationException) rootCause;
String bceBeanName = bce.getBeanName();
if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {
if (logger.isTraceEnabled()) {
logger.trace("Skipping advisor '" + name +
"' with dependency on currently created bean: " + ex.getMessage());
}
// Ignore: indicates a reference back to the bean we're trying to advise.
// We want to find advisors other than the currently created bean itself.
continue;
}
}
throw ex;
}
}
}
}
//返回集合
return advisors;
}
/**
* BeanFactoryAdvisorRetrievalHelper的方法
*
* 确定具有给定名称的切面 bean 是否合格,默认实现返回true
*/
protected boolean isEligibleBean(String beanName) {
return true;
}
该方法搜索给定的候选Advisors,查找可应用于指定bean的所有Advisors集合,简单的说,就是进行如下判断:
/**
* 搜索给定的候选Advisors,查找可应用于指定 bean 的所有Advisors
*
* @param candidateAdvisors 候选的Advisors
* @param beanClass 目标的beanClass
* @param beanName 目标的beanName
* @return 适用的Advisors
*/
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
//调用AopUtils.findAdvisorsThatCanApply方法查找
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
} finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
findAdvisorsThatCanApply方法内部还是调用AopUtils.findAdvisorsThatCanApply方法继续查找:
/**
* AopUtils的方法
*
* 确定适用于给定类的候选Advisors列表的子列表
*
* @param candidateAdvisors 候选的Advisors
* @param clazz 目标的beanClass
* @return 可应用于给定类对象的Advisors子列表,也可能就是传入列表
*/
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
//如果候选Advisors列表示空的,那么直接返回这个空列表
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
//合格的Advisors列表
List<Advisor> eligibleAdvisors = new ArrayList<>();
/*
* 处理引介增强,即 标签
* 子类AnnotationAwareAspectJAutoProxyCreator还会处理@DeclareParents注解
*/
//遍历候选列表
for (Advisor candidate : candidateAdvisors) {
//如果属于IntroductionAdvisor并且可以增强这个类,这里的canApply方法最终调用下面三个参数的canApply方法,第三个参数为false
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
//当前Advisor加入eligibleAdvisors集合
eligibleAdvisors.add(candidate);
}
}
//是否存在引介增强
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
//再次遍历候选列表
for (Advisor candidate : candidateAdvisors) {
//如果属于引介增强,表示已经处理过了,跳过
if (candidate instanceof IntroductionAdvisor) {
// already processed
continue;
}
//对其他的Advisor同样调用canApply方法判断,第三个参数为此前判断的是否存在引介增强,一般都是false
if (canApply(candidate, clazz, hasIntroductions)) {
//当前Advisor加入eligibleAdvisors集合
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
判断给定的advisor是否可以增强给定的class,简单的说就是检查class否符合advisor中的切入点表达式规则。
/**
* AopUtils的方法
*
* 给定的advisor是否可以增强给定的class,简单的说就是检查class否符合advisor中的切入点表达式规则
*
* @param advisor 要检查的advisor
* @param targetClass 目标的beanClass
* @param hasIntroductions 此类的Advisor链是否已包含introductions引介增强
* @return 给定的advisor是否可以增强给定的class
*/
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
/*
* 如果通知器属于引介增强,比如 标签的DeclareParentsAdvisor
*/
if (advisor instanceof IntroductionAdvisor) {
//判断目标的beanClass的路径是否包含在当前引介增强的类路径中,也就是是否匹配types-matching属性
//如果在增强类路径中,那么返回true,否则返回false
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
/*
* 如果通知器属于切入点增强
* 比如 标签的DefaultBeanFactoryPointcutAdvisor和各种通知标签的AspectJPointcutAdvisor
*/
else if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pca = (PointcutAdvisor) advisor;
//获取切入点通知器内部的切入点,继续判断给定的切入点能否在给定的类上适用
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
} else {
// 没有切入点,那么默认适用
return true;
}
}
对于切入点通知器实际上是匹配内部的切入点的execution表达式:
/**
* AopUtils的方法
*
* 判断给定的切入点能否在给定的类上适用?
*
* @param pc 要检查的方法切入点,常见就是AspectJExpressionPointcut
* @param targetClass 目标的beanClass
* @param hasIntroductions 此类的Advisor链是否已包含introductions引介增强
* @return 给定的advisor是否可以增强给定的class
*/
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
/*
* 1 匹配目标类的类路径是否满足切入点的execution表达式
*/
//如果目标的beanClass的路径不包含在当前切入点的类路径中,也就是execution表达式的类,路径那么直接返回false
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
/*
* 2 匹配目标类的方法是否至少有一个满足切入点的execution表达式
*/
//到这一步,表示目标的beanClass的路径包含在当前切入点的类路径中,下面进一步匹配方法
//获取当前切入点的方法匹配器,准备匹配方法,也就是execution表达式中定义的方法
MethodMatcher methodMatcher = pc.getMethodMatcher();
//如果匹配器是匹配所有方法,那么直接返回true
if (methodMatcher == MethodMatcher.TRUE) {
// No need to iterate the methods if we're matching any method anyway...
return true;
}
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}
//需要匹配方法的class集合
Set<Class<?>> classes = new LinkedHashSet<>();
//如果是普通类,那么加上当类自己的class
if (!Proxy.isProxyClass(targetClass)) {
classes.add(ClassUtils.getUserClass(targetClass));
}
//加上当前类的所有的接口的class
classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
//遍历集合
for (Class<?> clazz : classes) {
//获取所有方法
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
//一次匹配
for (Method method : methods) {
if (introductionAwareMethodMatcher != null ?
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
methodMatcher.matches(method, targetClass)) {
//如果匹配到任何一个,那么返回ture
return true;
}
}
}
//最终没有匹配任何一个方法,那么返回false
return false;
}
这个方法是用于扩展Advisors链的钩子方法,子类可重写该方法添加新的Advisor,或者对已存在的Advisor进行操作。
子类AnnotationAwareAspectJAutoProxyCreator重写了该方法,子类AspectJAwareAdvisorAutoProxyCreator继承了AnnotationAwareAspectJAutoProxyCreator。
/**
* AspectJAwareAdvisorAutoProxyCreator重写的方法
* AnnotationAwareAspectJAutoProxyCreator也会调用该方法
*
* 添加一个特殊的Advisor添加到Advisors链头部,使用一个特殊的拦截器ExposeInvocationInterceptor
* 用于向后面的拦截器暴露当前的 MethodInvocation
*/
@Override
protected void extendAdvisors(List<Advisor> candidateAdvisors) {
AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(candidateAdvisors);
}
添加一个特殊的Advisor到Advisors链头部,使用 AspectJ 切入点表达式和使用 AspectJ 样式的Advice时都需要添加,添加的是ExposeInvocationInterceptor.ADVISOR,实际类型是一个DefaultPointcutAdvisor类型的单例实例,它内部保存了ExposeInvocationInterceptor拦截器的单例实例,当进行拦截时Advisors链的第一个方法就是调用该拦截器的invoke方法。
这个拦截器的作用就是暴露当前MethodInvocation,实际操作就是将当前MethodInvocation存入一个ThreadLocal本地线程变量中,后续的拦截器可以直接通过ExposeInvocationInterceptor.currentInvocation()静态方法快速获取当前的MethodInvocation。
/**
* AspectJProxyUtils的方法
*
* 添加一个特殊的Advisor到Advisors链头部,使用 AspectJ 切入点表达式和使用 AspectJ 样式的Advice时都需要添加
* 添加的是ExposeInvocationInterceptor.ADVISOR,实际类型是一个DefaultPointcutAdvisor类型的单例实例
* 它内部保存了ExposeInvocationInterceptor拦截器的单例实例,当进行拦截时Advisors链的第一个方法就是调用该拦截器的invoke方法
* 这个拦截器的作用就是暴露当前MethodInvocation,实际操作就是将当前MethodInvocation存入一个ThreadLocal本地线程变量中,
* 后续的拦截器可以直接通过ExposeInvocationInterceptor.currentInvocation()静态方法快速获取当前的MethodInvocation
*
* @param advisors 可用的advisors
* @return 如果已添加,那么返回true,否则返回false
*/
public static boolean makeAdvisorChainAspectJCapableIfNecessary(List<Advisor> advisors) {
//不要将advisor添加到空列表中,这可能表示不需要代理
if (!advisors.isEmpty()) {
boolean foundAspectJAdvice = false;
for (Advisor advisor : advisors) {
// 是否存在AspectJAdvice类型的Advice,一般都存在
if (isAspectJAdvice(advisor)) {
foundAspectJAdvice = true;
break;
}
}
//如果存在AspectJAdvice类型的Advisor,并且不包含要添加的ExposeInvocationInterceptor.ADVISOR单例
if (foundAspectJAdvice && !advisors.contains(ExposeInvocationInterceptor.ADVISOR)) {
//将ExposeInvocationInterceptor.ADVISOR加入到advisors链的头部,在拦截时将会第一个调用
advisors.add(0, ExposeInvocationInterceptor.ADVISOR);
return true;
}
}
return false;
}
/**
* ExposeInvocationInterceptor的属性
* ExposeInvocationInterceptor的单例对象
*/
public static final ExposeInvocationInterceptor INSTANCE = new ExposeInvocationInterceptor();
/**
1. ExposeInvocationInterceptor的属性
2. DefaultPointcutAdvisor的单例对象,保存了INSTANCE单例
*/
public static final Advisor ADVISOR = new DefaultPointcutAdvisor(INSTANCE) {
@Override
public String toString() {
return ExposeInvocationInterceptor.class.getName() + ".ADVISOR";
}
};
对于Advisors链进行排序,保证调用顺序。
PartialOrder.sort方法涉及到偏序排序和图形映射,我们后面有机会再讲解源码!
/**
* AspectJAwareAdvisorAutoProxyCreator的属性
*
* 根据 AspectJ 优先级对提供的Advisor实例进行排序的比较器
*/
private static final Comparator<Advisor> DEFAULT_PRECEDENCE_COMPARATOR = new AspectJPrecedenceComparator();
/**
* AspectJAwareAdvisorAutoProxyCreator的方法
*
* 根据 AspectJ 优先级对提供的Advisor实例进行排序
*/
@Override
protected List<Advisor> sortAdvisors(List<Advisor> advisors) {
List<PartiallyComparableAdvisorHolder> partiallyComparableAdvisors = new ArrayList<>(advisors.size());
//Advisor封装成为PartiallyComparableAdvisorHolder对象,它是AspectJAwareAdvisorAutoProxyCreator的内部类
//并将加入PartiallyComparableAdvisorHolder对象partiallyComparableAdvisors集合中,使用AspectJPrecedenceComparator比较器
for (Advisor advisor : advisors) {
partiallyComparableAdvisors.add(
new PartiallyComparableAdvisorHolder(advisor, DEFAULT_PRECEDENCE_COMPARATOR));
}
/*
* 通过PartialOrder.sort排序,这里的排序仅仅是采用的"偏序排序",并且采用了图形结构
*/
List<PartiallyComparableAdvisorHolder> sorted = PartialOrder.sort(partiallyComparableAdvisors);
/*还原排序之后的数据*/
if (sorted != null) {
List<Advisor> result = new ArrayList<>(advisors.size());
for (PartiallyComparableAdvisorHolder pcAdvisor : sorted) {
result.add(pcAdvisor.getAdvisor());
}
return result;
} else {
//如果无法排序,那么采用父类的排序方式
return super.sortAdvisors(advisors);
}
}
为给定的 bean 创建 AOP 代理。这一步会选择到底是通过JDK代理创建还是通过CGLIB代理创建。
/**
* bean工厂,通过BeanFactoryAware回调设置
*/
@Nullable
private BeanFactory beanFactory;
/**
*
* 指示是否应冻结代理并且无法更改任何advice。
*/
private boolean freezeProxy = false;
/**
* AbstractAutoProxyCreator的方法
*
* 为给定的 bean 创建 AOP 代理
*
* @param beanClass beanClass
* @param beanName beanName
* @param specificInterceptors 当前bean可用的Advisor通知器链
* @param targetSource 代理的目标源
* @return bean的 Aop 代理
*/
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
//公开指定 bean 的给定目标类,主要就是设置bean定义的ORIGINAL_TARGET_CLASS_ATTRIBUTE属性,
//即"org.springframework.aop.framework.autoproxy.AutoProxyUtils.originalTargetClass"属性,value为beanClass
//也就是保存其原来的类型
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
//新建一个ProxyFactory代理工厂对象,用于创建代理
ProxyFactory proxyFactory = new ProxyFactory();
//从当前AbstractAutoProxyCreator拷贝属性,实际上就是拷贝ProxyConfig内部的几个属性
proxyFactory.copyFrom(this);
/*
* 检查proxyTargetClass属性,判断是走哪种代理方式
* proxyTargetClass默认是false的,即先尝试走JDK代理,不行再走CGLIB代理
* 如果设置为true,那么就强制走CGLIB代理
*
* 可通过 、 标签的proxy-target-class的属性设置,默认false
* 或者@EnableAspectJAutoProxy注解的proxyTargetClass属性设置,默认false
*/
/*
* 即使proxyTargetClass属性为false,那么还要继续校验,或者评估接口
*/
if (!proxyFactory.isProxyTargetClass()) {
/*
* 继续检查当前bean对应的bean定义的PRESERVE_TARGET_CLASS_ATTRIBUTE属性,即"org.springframework.aop.framework.autoproxy
* .AutoProxyUtils.preserveTargetClass"属性,如果存在该属性,并且值为true
*
* 我们在前面讲解"ConfigurationClassPostProcessor配置类后处理器"的文章中就见过该属性
* 对于@Configuration注解标注的代理类,它的bean定义会添加这个属性并且值为true,表示强制走CGLIB代理
*/
if (shouldProxyTargetClass(beanClass, beanName)) {
//那么将proxyTargetClass改为true,表示还是走基于类的CGLIB代理
proxyFactory.setProxyTargetClass(true);
} else {
/*
* 评估需要代理的接口,添加到proxyFactory中
* 如果没有至少一个合理的代理接口,那么仍然会走基于类的CGLIB代理
*/
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
//构建给定 bean 的advisors拦截器链,包括特定的拦截器以及公共拦截器,并且将这些都适配成Advisor接口体系
//比如MethodInterceptor方法拦截器将被包装成为一个DefaultPointcutAdvisor
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
//advisors添加到proxyFactory的advisors属性集合中
proxyFactory.addAdvisors(advisors);
//targetSource添加到proxyFactory的targetSource属性中,通过此可以获取源目标对象
proxyFactory.setTargetSource(targetSource);
//继续自定义ProxyFactory钩子方法,默认空实现,留给子类实现
//目前版本还没有内置的子类实现这个方法
customizeProxyFactory(proxyFactory);
//设置frozen属性,表示指示是否应冻结代理并且无法更改任何advice,默认false
proxyFactory.setFrozen(this.freezeProxy);
//判断是否已对advisors进行ClassFilter筛选,如果已苏筛选,那么后续在生成 AOP 调用的advisors链时跳过 ClassFilter 检查
//默认返回false,即没有进行筛选
if (advisorsPreFiltered()) {
//设置proxyFactory的preFiltered属性为true,表示已筛选
proxyFactory.setPreFiltered(true);
}
/*
* 通过proxyFactory获取代理对象
*/
return proxyFactory.getProxy(getProxyClassLoader());
}
公开要代理的指定 bean 的原始类。实际上就是存入当前bean对应的ORIGINAL_TARGET_CLASS_ATTRIBUTE属性中,也就是"org.springframework.aop.framework.autoproxy.AutoProxyUtils.originalTargetClass"属性。
我们在前面讲解ConfigurationClassPostProcessor配置类后处理器的文章中就说过,这种“属性”并不是存储在BeanDefinition中,而是存放在BeanDefinition实际类型的父类AttributeAccessorSupport的attributes缓存中,该缓存属于对象级别,每一个bean定义都有自己的attributes缓存,因此不会共享。
/**
* AutoProxyUtils的方法
*
* 公开指定 bean 的原始类
*/
static void exposeTargetClass(
ConfigurableListableBeanFactory beanFactory, @Nullable String beanName, Class<?> targetClass) {
if (beanName != null && beanFactory.containsBeanDefinition(beanName)) {
//设置一个ORIGINAL_TARGET_CLASS_ATTRIBUTE属性,值为targetClass
beanFactory.getMergedBeanDefinition(beanName).setAttribute(ORIGINAL_TARGET_CLASS_ATTRIBUTE, targetClass);
}
}
/**
* Bean definition属性key,指示自动代理Bean的原始目标类,例如用于在基于接口的代理之后对目标类上的注解进行内省
* 确定值为:"org.springframework.aop.framework.autoproxy.AutoProxyUtils.originalTargetClass"
*/
public static final String ORIGINAL_TARGET_CLASS_ATTRIBUTE =
Conventions.getQualifiedAttributeName(AutoProxyUtils.class, "originalTargetClass");
即使获取的proxyTargetClass属性为false,那么仍然需要调用shouldProxyTargetClass方法继续校验。继续检查当前bean对应的bean定义的PRESERVE_TARGET_CLASS_ATTRIBUTE属性,即"org.springframework.aop.framework.autoproxy.AutoProxyUtils.preserveTargetClass"属性,如果存在该属性,并且值为true。那么仍然需要使用基于类的代理,即CGLIB代理。
为什么这么做呢?实际上,我们在前面讲解ConfigurationClassPostProcessor配置类后处理器的文章中就见过该属性,对于@Configuration注解标注的配置类,它的bean定义会添加这个属性并且赋值为true,表示@Configuration配置类对象需要强制走CGLIB代理,至于为什么需要创建代理,在那篇文章中也说过了,这里的校验就是为了满足这个要求。
/**
* AbstractAutoProxyCreator的方法
*
* 指示给定 bean 是否应使用基于类的代理,即CGLIB代理
*/
protected boolean shouldProxyTargetClass(Class<?> beanClass, @Nullable String beanName) {
return (this.beanFactory instanceof ConfigurableListableBeanFactory &&
//调用AutoProxyUtils.shouldProxyTargetClass方法
AutoProxyUtils.shouldProxyTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName));
}
/**
* AutoProxyUtils的属性
*
* 指示给定 bean 是否应使用基于类的代理,即CGLIB代理
* 如果希望代理bean可以转化内目标bean类型,那么可以设置该属性并且值为true
* 确定值为:"org.springframework.aop.framework.autoproxy.AutoProxyUtils.preserveTargetClass"
*/
public static final String PRESERVE_TARGET_CLASS_ATTRIBUTE =
Conventions.getQualifiedAttributeName(AutoProxyUtils.class, "preserveTargetClass");
/**
* AutoProxyUtils的方法
*
* 通过检查相应的PRESERVE_TARGET_CLASS_ATTRIBUTE属性,确定给定 bean 是否应与其目标类而不是接口进行代理。
*/
public static boolean shouldProxyTargetClass(
ConfigurableListableBeanFactory beanFactory, @Nullable String beanName) {
if (beanName != null && beanFactory.containsBeanDefinition(beanName)) {
BeanDefinition bd = beanFactory.getBeanDefinition(beanName);
//如果具有PRESERVE_TARGET_CLASS_ATTRIBUTE属性并且值为true,那么表示应该使用基于类的代理
return Boolean.TRUE.equals(bd.getAttribute(PRESERVE_TARGET_CLASS_ATTRIBUTE));
}
return false;
}
如果shouldProxyTargetClass方法返回false,那么调用evaluateProxyInterfaces方法,继续检查给定 bean 类上的接口,如果存在至少一个合理的接口,那么将所有接口都设置到ProxyFactory的interfaces集合中,如果没有筛选到至少一个合理的代理接口,仍然退回到基于类的CGLIB代理,将proxyTargetClass改为true。
如果当前接口不是一个容器回调接口(isConfigurationCallbackInterface返回false),并且当前接口不是内部语言接口(isInternalLanguageInterface返回false),并且接口方法个数至少为1个(不是标志性接口)。同时满足上面三个条件,当前接口就是一个合理的代理接口。
/**
* ProxyProcessorSupport的方法
*
*
* 检查给定 bean 类上的接口,并将其应用于ProxyFactory
*
* 调用 isConfigurationCallbackInterface和isInternalLanguageInterface方法以筛选合理的代理接口
* 如果没有筛选到至少一个合理的代理接口,仍然退回到基于类的CGLIB代理
*
* @param beanClass beanClass
* @param proxyFactory bean的代理工厂
*/
protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) {
//获取当前类实现的所有接口的class数组
Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader());
//是否具有合理的代理的接口,默认false
boolean hasReasonableProxyInterface = false;
//遍历全部接口class数组,查找是否具有合理的代理的接口
for (Class<?> ifc : targetInterfaces) {
//如果当前接口不是一个容器回调接口,并且当前接口不是内部语言接口,并且接口方法个数至少为1个(不是标志性接口)
//同时满足上面三个条件,当前接口就是一个合理的代理接口
if (!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) &&
ifc.getMethods().length > 0) {
//hasReasonableProxyInterface设置为true,结束循环
hasReasonableProxyInterface = true;
break;
}
}
//如果具有合理的代理的接口
if (hasReasonableProxyInterface) {
//再次遍历全部接口class数组,将接口存入proxyFactory的interfaces集合中
for (Class<?> ifc : targetInterfaces) {
proxyFactory.addInterface(ifc);
}
} else {
//如果没有合理的代理的接口,那么将proxyTargetClass改为true,表示还是走基于类的CGLIB代理
proxyFactory.setProxyTargetClass(true);
}
}
判断给定的接口是否只是一个容器回调接口,如果是,那么将不被视为合理的代理接口,将返回true。
如果接口属于InitializingBean、DisposableBean、Closeable、AutoCloseable接口以及Aware接口包括其子接口,那么这个接口就是一个容器回调接口,将不被视为合理的代理接口。
/**
* ProxyProcessorSupport的方法
*
* 判断给定的接口是否只是一个容器回调接口,如果是,那么将不被视为合理的代理接口。
*
* @param ifc 要检查的接口
* @return 给定接口是否只是一个容器回调接口
*/
protected boolean isConfigurationCallbackInterface(Class<?> ifc) {
//如果接口属于InitializingBean、DisposableBean、Closeable、AutoCloseable接口以及Aware接口包括其子接口之一
//那么这个接口就是一个容器回调接口,将不被视为合理的代理接口。
return (InitializingBean.class == ifc || DisposableBean.class == ifc || Closeable.class == ifc ||
AutoCloseable.class == ifc || ObjectUtils.containsElement(ifc.getInterfaces(), Aware.class));
}
判断给定的接口是否是众所周知的内部语言接口,如果是,那么将不被视为合理的代理接口,将返回true。
如果接口的全路径名等于"groovy.lang.GroovyObject",或者以".cglib.proxy.Factory"结尾,或者以".bytebuddy.MockAccess"结尾。那么这个接口就是一个内部语言接口,将不被视为合理的代理接口。也就是说这种接口只能是框架内部使用,我们开发者不应该使用。
/**
* ProxyProcessorSupport的方法
*
* 判断给定的接口是否是众所周知的内部语言接口,如果是,那么将不被视为合理的代理接口。
*
* 如果接口的全路径名等于"groovy.lang.GroovyObject",或者以".cglib.proxy.Factory"结尾,或者以".bytebuddy.MockAccess"结尾
* 那么这个接口就是一个内部语言接口,将不被视为合理的代理接口。也就是说这种接口只能是框架内部使用,我们开发者不应该使用
*
* @param ifc 要检查的接口
* @return 给定的接口是否为内部语言接口
*/
protected boolean isInternalLanguageInterface(Class<?> ifc) {
return (ifc.getName().equals("groovy.lang.GroovyObject") ||
ifc.getName().endsWith(".cglib.proxy.Factory") ||
ifc.getName().endsWith(".bytebuddy.MockAccess"));
}
通过proxyFactory获取代理对象,实际上内部还是现获取对应类型的AopProxy,然后通过AopProxy获取代理对象。
AopProxy是AOP代理对象的抽象接口,提供了两个getProxy方法,用于获取实际的AopProxy对象。
/**
* ProxyFactory的方法
*
* 根据此proxyFactory的创建新代理对象
* 可以重复调用。如果我们添加了或删除接口,效果会有所不同。可以添加和删除拦截器。
*
* @param classLoader 类加载器用于创建代理
* @return 代理对象
*/
public Object getProxy(@Nullable ClassLoader classLoader) {
//创建AopProxy,通过AOP代理获取代理对象
return createAopProxy().getProxy(classLoader);
}
内部又是通过AopProxyFactory创建指定类型的AopProxy,默认AopProxyFactory类型为DefaultAopProxyFactory,随后通过DefaultAopProxyFactory的createAopProxy方法创建AopProxy对象。
/**
* ProxyCreatorSupport的方法
*
* 创建AopProxy
*/
protected final synchronized AopProxy createAopProxy() {
//如果没有激活,那么激活代理配置,只会在创建第一个 AOP 代理时激活一次
if (!this.active) {
activate();
}
/*
* 通过AopProxyFactory创建指定类型的AopProxy,默认AopProxyFactory类型为DefaultAopProxyFactory
* 随后通过DefaultAopProxyFactory的createAopProxy方法创建AopProxy对象
*/
return getAopProxyFactory().createAopProxy(this);
}
//---------ProxyCreatorSupport的相关属性---------
/**
*
* 创建第一个 AOP 代理时设置为 true
*/
private boolean active = false;
/**
* 激活代理的监听器集合,默认空集合
*/
private final List<AdvisedSupportListener> listeners = new LinkedList<>();
/**
1. 激活此代理配置,实际上就是在创建第一个 AOP 代理时发布监听事件
*/
private void activate() {
//active设置为true
this.active = true;
//遍历listeners监听器集合,默认空集合
for (AdvisedSupportListener listener : this.listeners) {
//创建第一个代理时调用
listener.activated(this);
}
}
DefaultAopProxyFactory的方法,根据配置类型选择创建JDK或者CGLIB类型的AopProxy并返回。 大概逻辑如下:
可以看到,这里的真实逻辑和平时所说的逻辑有些许差别,但是大抵如此!
/**
* DefaultAopProxyFactory的方法
*
* 根据配置类型选择创建AopProxy的类型
*
* @param config AOP配置,就是前面的proxyFactory对象
*/
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
//如果isOptimize返回true,即optimize属性为true,表示CGLIB代理应该主动进行优化,默认false
//或者,如果isProxyTargetClass返回true,即proxyTargetClass属性为true,表示应该使用CGLIB代理,默认false
//或者,如果hasNoUserSuppliedProxyInterfaces返回true,表示没有可使用的代理接口或者只有一个代理接口并且属于SpringProxy接口体系
//即校验interfaces集合,这个集合就是在此前evaluateProxyInterfaces方法中加入的接口集合
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
//获取目标类型
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.");
}
//如果目标类型是接口,或者目标类型就是Proxy类型
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
//那么采用JDK的AopProxy,proxyFactory作为构造器参数
return new JdkDynamicAopProxy(config);
}
//默认采用CGLIB的AopProxy,proxyFactory作为构造器参数
return new ObjenesisCglibAopProxy(config);
} else {
//以上三个条件都不满足
//否则,采用JDK的AopProxy,proxyFactory作为构造器参数
return new JdkDynamicAopProxy(config);
}
}
/**
* DefaultAopProxyFactory的方法
*
* 确定是否没有可使用的代理接口,或者只有一个代理接口并且属于SpringProxy接口体系
*/
private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
//获取内部的interfaces集合,这个集合就是在此前evaluateProxyInterfaces方法中加入的接口集合
Class<?>[] ifcs = config.getProxiedInterfaces();
//如果是一个空集合,表示没有可使用的代理接口,或者只有一个代理接口并且属于SpringProxy接口体系,那么返回true
return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
}
新建一个基于JDK的AopProxy,即JdkDynamicAopProxy,将前面的proxyFactory对象赋给advised属性。
/**
* 用于配置此代理的配置,就是前面的proxyFactory对象
*/
private final AdvisedSupport advised;
/**
* 通过给定的 AOP 配置构建新的 JdkDynamicAopProxy
*
* @param config AOP配置,就是前面的proxyFactory对象
*/
public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
Assert.notNull(config, "AdvisedSupport must not be null");
if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
throw new AopConfigException("No advisors and no TargetSource specified");
}
//赋给advised属性
this.advised = config;
}
新建一个基于CGLIB的AopProxy,即ObjenesisCglibAopProxy,将前面的proxyFactory对象赋给advised属性。后续调用ObjenesisCglibAopProxy对象的方法时,会调用它的intercept方法。
/**
* 通过给定的 AOP 配置创建新的 ObjenesisCglibAopProxy。
*
* @param config AOP配置,就是前面的proxyFactory对象
*/
public ObjenesisCglibAopProxy(AdvisedSupport config) {
//调用父类CglibAopProxy的构造器
super(config);
}
/**
* 用于配置此代理的配置,就是前面的proxyFactory对象
*/
protected final AdvisedSupport advised;
/**
* 通过给定的 AOP 配置创建新的 CglibAopProxy
*
* @param config AOP配置,就是前面的proxyFactory对象
*/
public CglibAopProxy(AdvisedSupport config) throws AopConfigException {
Assert.notNull(config, "AdvisedSupport must not be null");
if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
throw new AopConfigException("No advisors and no TargetSource specified");
}
//赋给advised属性
this.advised = config;
this.advisedDispatcher = new AdvisedDispatcher(this.advised);
}
可以看到,最终就是通过熟悉的Proxy.newProxyInstance方法来创建代理对象的,如果我们了解过最基本的动态代理模式,那么这个方法应该很熟悉了,这就是JDK动态代理获取代理对象的方式,它创建代理对象使用的类库Proxy来自JDK的核心rt.jar包。
newProxyInstance方法的第一个参数是类加载器,第二个参数就是代理类对象需要实现的接口数组,第三个参数就是当前JdkDynamicAopProxy对象,作为调用处理程序。当代理对象在调用方法时,方法调用被分派到调用处理程序的invoke方法,即JdkDynamicAopProxy对象的invoke方法,这个invoke方法定义了代理对象的额外的行为,也就是如果对原始对象和方法进行增强的逻辑!
/**
* JdkDynamicAopProxy的方法
*
* 采用JDK动态代理获取代理对象
*/
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
//获取全部需要代理的接口数组,主要目的是判断如果interfaces集合(evaluateProxyInterfaces方法中加入的接口集合)中没有
//SpringProxy、Advised、DecoratingProxy这些接口,则尝试将SpringProxy、Advised、DecoratingProxy
//这三个接口添加到数组后三位,原本的interfaces集合中缺哪一个就添加哪一个,这表示新创建代理对象将实现这些接口
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
//查找接口集中是否有接口存在equals方法或者hashCode方法,有的话分别标记equalsDefined和hashCodeDefined字段
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
//通过Proxy创建代理对象,这是JDK自带的方式
//第一个参数是类加载器,第二个参数就是代理类对象需要实现的接口数组,第三个参数就是当前JdkDynamicAopProxy对象,作为调用处理程序
//因此当调用代理对象的方法时,将会方法调用被分派到调用处理程序的invoke方法,即JdkDynamicAopProxy对象的invoke方法
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
确定需要代理的完整接口集,通常,会尝试在interfaces接口集的基础上追加代理三个接口SpringProxy、Advised、DecoratingProxy。
/**
* JdkDynamicAopProxy的方法
*
* 确定给定 AOP 配置的代理的完整接口集
* 通常,会尝试追加三个接口SpringProxy、Advised、DecoratingProxy
*
* @param advised AOP配置,就是前面的proxyFactory对象
* @param decoratingProxy 是否公开DecoratingProxy接口
* @return 完整的代理接口集
*/
static Class<?>[] completeProxiedInterfaces(AdvisedSupport advised, boolean decoratingProxy) {
//获取proxyFactory的interfaces接口集(evaluateProxyInterfaces方法中加入的接口集合)
Class<?>[] specifiedInterfaces = advised.getProxiedInterfaces();
//如果是一个空集
if (specifiedInterfaces.length == 0) {
// No user-specified interfaces: check whether target class is an interface.
//获取目标类型
Class<?> targetClass = advised.getTargetClass();
if (targetClass != null) {
//如果目标类型是集合,那么目标类型加入到interfaces接口集中
if (targetClass.isInterface()) {
advised.setInterfaces(targetClass);
}
//如果是Proxy类型
if (Proxy.isProxyClass(targetClass)) {
//将目标类型实现的接口加入到interfaces接口集中
advised.setInterfaces(targetClass.getInterfaces());
}
//重新获取proxyFactory的interfaces接口集
specifiedInterfaces = advised.getProxiedInterfaces();
}
}
//是否需要追加SpringProxy接口,如果原本interfaces接口集中没有SpringProxy接口,那就追加,否则不追加
boolean addSpringProxy = !advised.isInterfaceProxied(SpringProxy.class);
//是否需要追加Advised接口,如果不需要阻止代理类转换为Advised类型(判断opaque属性,默认为false)
//并且原本interfaces接口集中没有Advised接口,那就追加,否则不追加
boolean addAdvised = !advised.isOpaque() && !advised.isInterfaceProxied(Advised.class);
//是否需要追加DecoratingProxy接口,如果需要公开DecoratingProxy接口
//并且原本interfaces接口集中没有DecoratingProxy接口,那就追加,否则不追加
boolean addDecoratingProxy = (decoratingProxy && !advised.isInterfaceProxied(DecoratingProxy.class));
/*
* 尝试根据上面的判断将这三个接口追加到要返回的接口集尾部
* 注意并没有追加到interfaces接口集中
*/
int nonUserIfcCount = 0;
if (addSpringProxy) {
nonUserIfcCount++;
}
if (addAdvised) {
nonUserIfcCount++;
}
if (addDecoratingProxy) {
nonUserIfcCount++;
}
Class<?>[] proxiedInterfaces = new Class<?>[specifiedInterfaces.length + nonUserIfcCount];
System.arraycopy(specifiedInterfaces, 0, proxiedInterfaces, 0, specifiedInterfaces.length);
int index = specifiedInterfaces.length;
if (addSpringProxy) {
proxiedInterfaces[index] = SpringProxy.class;
index++;
}
if (addAdvised) {
proxiedInterfaces[index] = Advised.class;
index++;
}
if (addDecoratingProxy) {
proxiedInterfaces[index] = DecoratingProxy.class;
}
return proxiedInterfaces;
}
查找在接口集上(interfaces)的任何equals或者hashCode方法,并标记JdkDynamicAopProxy对象的相关属性:
//------------JdkDynamicAopProxy的相关属性-------------
/**
* 接口集合(interfaces)中是否存在某个集合有equals方法
*/
private boolean equalsDefined;
/**
* 接口集合(interfaces)中是否存在某个集合有hashCode方法
*/
private boolean hashCodeDefined;
/**
* JdkDynamicAopProxy的方法
*
* 查找在接口集上的任何equals或者hashCode方法,并进行标记
*
* @param proxiedInterfaces 接口数组
*/
private void findDefinedEqualsAndHashCodeMethods(Class<?>[] proxiedInterfaces) {
//遍历接口数组
for (Class<?> proxiedInterface : proxiedInterfaces) {
//获取当前接口自己的所有方法数组
Method[] methods = proxiedInterface.getDeclaredMethods();
//遍历方法数组
for (Method method : methods) {
//如果存在equals方法,那么equalsDefined设置为true
if (AopUtils.isEqualsMethod(method)) {
this.equalsDefined = true;
}
//如果存在hashCode方法,那么hashCodeDefined设置为true
if (AopUtils.isHashCodeMethod(method)) {
this.hashCodeDefined = true;
}
//如果找到有些集合存在这些方法,那么直接返回,不需要在查找了
if (this.equalsDefined && this.hashCodeDefined) {
return;
}
}
}
}
采用CGLIB动态代理获取代理对象,最终就是先通过创建的Enhancer增强器来获取代理类的class,随后直接通过objenesis绕过构造器创建代理类对象或者通过反射调用代理类的构造器创建代理类对象。
当进行方法调用的时候,第一个调用的是拦截器链头部的DynamicAdvisedInterceptor的intercept方法!
/**
* AOP配置,就是前面的proxyFactory对象
*/
protected final AdvisedSupport advised;
/**
* ObjenesisCglibAopProxy的父类CglibAopProxy的方法
*
* 采用CGLIB动态代理获取代理对象
*/
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
}
try {
//获取目标类
Class<?> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
//将目标类作为代理类的父类
Class<?> proxySuperClass = rootClass;
//通过判断类名是否包含"$$"来判断目标类是否同样是由CGLIB生成的类,如果是
if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
//进一步获取目标类的父类,作为代理类的父类
proxySuperClass = rootClass.getSuperclass();
//获取目标类的接口
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
//加入到advised中的interfaces集合中
for (Class<?> additionalInterface : additionalInterfaces) {
this.advised.addInterface(additionalInterface);
}
}
//检验代理类的父类,并输出日志。
//检查给定class上的final方法,以及跨 ClassLoaders 的包可见方法,并将警告写入日志
validateClassIfNecessary(proxySuperClass, classLoader);
/*
* 创建并配置CGLIB的Enhancer增强器,CGLIB就是通过Enhancer来创建代理对象的
*/
//创建Enhancer
Enhancer enhancer = createEnhancer();
//配置Enhancer
if (classLoader != null) {
//设置类加载器
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
//设置继承的父类为目标类型
enhancer.setSuperclass(proxySuperClass);
//设置实现的接口,这个completeProxiedInterfaces方法前面说过了
//所以说,通过CGLIB创建的代理类对象也是实现了接口的,至少会实现SpringProxy和Advised接口
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
//设置类名命名策略
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
//设置设置用于从此生成器创建字节码的策略
enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));
//获取全部需要回调的拦截器链数组,记住,第一个拦截器就是DynamicAdvisedInterceptor ,封装了全部增强的方法
Callback[] callbacks = getCallbacks(rootClass);
//全部拦截器的class数组
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
// fixedInterceptorMap only populated at this point, after getCallbacks call above
//设置回调过滤器
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
//设置回调类型
enhancer.setCallbackTypes(types);
//根据enhancer和callbacks生成代理类并创建代理实例。
//该方法被子类ObjenesisCglibAopProxy重写
return createProxyClassAndInstance(enhancer, callbacks);
} catch (CodeGenerationException | IllegalArgumentException ex) {
throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
": Common causes of this problem include using a final class or a non-visible class",
ex);
} catch (Throwable ex) {
// TargetSource.getTarget() failed
throw new AopConfigException("Unexpected AOP exception", ex);
}
}
校验提供的代理类的父类(通常就是目标类),并输出日志。检查给定class上的final方法,以及跨 ClassLoaders 的包可见方法,并将警告写入日志。
/**
* 跟踪为对final方法进行验证的类
*/
private static final Map<Class<?>, Boolean> validatedClasses = new WeakHashMap<>();
/**
* 检查提供的代理类的父类是否已经验证,如果没有,则验证它。
*/
private void validateClassIfNecessary(Class<?> proxySuperClass, @Nullable ClassLoader proxyClassLoader) {
if (logger.isWarnEnabled()) {
synchronized (validatedClasses) {
//如果不包含该class,表示还没有校验
if (!validatedClasses.containsKey(proxySuperClass)) {
//校验该class
doValidateClass(proxySuperClass, proxyClassLoader,
ClassUtils.getAllInterfacesForClassAsSet(proxySuperClass));
//存入validatedClasses缓存
validatedClasses.put(proxySuperClass, Boolean.TRUE);
}
}
}
}
/**
* 检查给定class上的最终方法,以及跨 ClassLoaders 的包可见方法,并将警告写入日志
*/
private void doValidateClass(Class<?> proxySuperClass, @Nullable ClassLoader proxyClassLoader, Set<Class<?>> ifcs) {
if (proxySuperClass != Object.class) {
//获取全部方法
Method[] methods = proxySuperClass.getDeclaredMethods();
for (Method method : methods) {
int mod = method.getModifiers();
//如果不是静态的并且不是private的
if (!Modifier.isStatic(mod) && !Modifier.isPrivate(mod)) {
//如果是final的,输入警告日志
if (Modifier.isFinal(mod)) {
if (logger.isInfoEnabled() && implementsInterface(method, ifcs)) {
logger.info("Unable to proxy interface-implementing method [" + method + "] because " +
"it is marked as final: Consider using interface-based JDK proxies instead!");
}
if (logger.isDebugEnabled()) {
logger.debug("Final method [" + method + "] cannot get proxied via CGLIB: " +
"Calls to this method will NOT be routed to the target instance and " +
"might lead to NPEs against uninitialized fields in the proxy instance.");
}
}
//如果不是public的并且不是protected的并且类加载器不一致,那么输出警告
else if (logger.isDebugEnabled() && !Modifier.isPublic(mod) && !Modifier.isProtected(mod) &&
proxyClassLoader != null && proxySuperClass.getClassLoader() != proxyClassLoader) {
logger.debug("Method [" + method + "] is package-visible across different ClassLoaders " +
"and cannot get proxied via CGLIB: Declare this method as public or protected " +
"if you need to support invocations through the proxy.");
}
}
}
//递归校验父class
doValidateClass(proxySuperClass.getSuperclass(), proxyClassLoader, ifcs);
}
}
获取回调拦截器数组,方法很复杂,我们只需要记住,第一个拦截器就是DynamicAdvisedInterceptor ,封装了全部增强的方法。
当进行方法调用的时候,第一个调用的也是拦截器链头部的DynamicAdvisedInterceptor的intercept方法!
/**
1. ObjenesisCglibAopProxy的父类CglibAopProxy的方法
2.
3. 获取回调拦截器数组
4. 我们只需要记住,第一个拦截器就是DynamicAdvisedInterceptor ,封装了全部增强的方法
5. 6. @param rootClass 目标类
7. @return 回调拦截器数组
*/
private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
/*一系列用于优化选择的参数...*/
//判断exposeProxy属性,也就是否需要暴露代理对象,这个属性就是最开始设置的expose-proxy属性
//另外,在JdkDynamicAopProxy的invoke方法中也用到了该属性,默认是false
boolean exposeProxy = this.advised.isExposeProxy();
//判断frozen属性,也就是是否需要优化CGLIB,默认false
boolean isFrozen = this.advised.isFrozen();
//判断目标源是否是静态的,用于判断每次调用getTarget方法是否会返回同一个对象(是否会被TargetSource缓存),SingletonTargetSource目标源是静态的,其他目标源默认都是非静态的,大部分普通类都是SingletonTargetSource类型的目标源,LazyInitTargetSource实际上也会缓存,但是它是非静态的。
boolean isStatic = this.advised.getTargetSource().isStatic();
// Choose an "aop" interceptor (used for AOP calls).
//创建一个"aop"拦截器(用于 AOP 调用),内部封装了增强方法
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
// Choose a "straight to target" interceptor. (used for calls that are
// unadvised but can return this). May be required to expose the proxy.
//新建目标拦截器
Callback targetInterceptor;
//如果需要暴露代理对象,
if (exposeProxy) {
//
targetInterceptor = (isStatic ?
//当代理要公开时的方法拦截器,用于没有advice链的静态目标
new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
//当代理需要公开时,未通知的动态目标的拦截器
new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));
}
//不需要暴露代理对象
else {
//
targetInterceptor = (isStatic ?
//方法拦截器,用于没有advice链的静态目标
new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
//拦截器用于调用动态目标
new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));
}
// Choose a "direct to target" dispatcher (used for
// unadvised calls to static targets that cannot return this).
//目标转发器
Callback targetDispatcher = (isStatic ?
new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());
//主要的回调拦截器链数组,aopInterceptor是放在第一位的,将会第一个调用
Callback[] mainCallbacks = new Callback[]{
aopInterceptor, // for normal advice
targetInterceptor, // invoke target without considering advice, if optimized
new SerializableNoOp(), // no override for methods mapped to this
targetDispatcher, this.advisedDispatcher,
new EqualsInterceptor(this.advised),
new HashCodeInterceptor(this.advised)
};
Callback[] callbacks;
// If the target is a static one and the advice chain is frozen,
// then we can make some optimizations by sending the AOP calls
// direct to the target using the fixed chain for that method.
//一系列优化
if (isStatic && isFrozen) {
Method[] methods = rootClass.getMethods();
Callback[] fixedCallbacks = new Callback[methods.length];
this.fixedInterceptorMap = new HashMap<>(methods.length);
// TODO: small memory optimization here (can skip creation for methods with no advice)
for (int x = 0; x < methods.length; x++) {
Method method = methods[x];
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, rootClass);
fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
this.fixedInterceptorMap.put(method, x);
}
// Now copy both the callbacks from mainCallbacks
// and fixedCallbacks into the callbacks array.
callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
this.fixedInterceptorOffset = mainCallbacks.length;
} else {
callbacks = mainCallbacks;
}
//返回callbacks
return callbacks;
}
根据enhancer和callbacks生成代理类并创建代理实例。该方法被子类ObjenesisCglibAopProxy重写。
在子类ObjenesisCglibAopProxy中,首先通过Enhancer创建代理子类的class,随后的代理子类的实例化则分情况讨论:
/**
* ObjenesisCglibAopProxy的属性
*
* 一个Objenesis工具对象,用于生成某个类型的实例
*
* 关于Objenesis:http://objenesis.org/
* 它是一个小类库,可以通过绕过对象的构造函数的要求来创建某个类的对象实例
* 即在不调用构造函数的情况下实例化对象,当然我们也可以通过Unsafe来完成
*/
private static final SpringObjenesis objenesis = new SpringObjenesis();
/**
* ObjenesisCglibAopProxy的方法
*
* 根据enhancer和callbacks生成代理类并创建代理实例
*
* @param enhancer 增强器
* @param callbacks 回调链
* @return CGLIB代理类对象
*/
@Override
protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
//通过Enhancer创建代理子类class
Class<?> proxyClass = enhancer.createClass();
Object proxyInstance = null;
//通过判断objenesis的worthTrying属性是否不等于Boolean.FALSE对象,来确定是否值得通过Objenesis来生成代理类的实例
//worthTrying属性默认为null,不等于Boolean.FALSE对象,因此一般都是走这个逻辑
if (objenesis.isWorthTrying()) {
try {
//通过objenesis绕过构造器创建代理类对象,即不需要调用任何构造器
proxyInstance = objenesis.newInstance(proxyClass, enhancer.getUseCache());
} catch (Throwable ex) {
logger.debug("Unable to instantiate proxy using Objenesis, " +
"falling back to regular proxy construction", ex);
}
}
//如果proxyInstance还是为null,那么尝试通过反射代理类的无参构造器创建代理类对象
if (proxyInstance == null) {
// Regular instantiation via default constructor...
try {
//如果没手动设置constructorArgs构造器参数,默认不会设置,那么获取无参构造器,否则获取对应参数的构造器
Constructor<?> ctor = (this.constructorArgs != null ?
proxyClass.getDeclaredConstructor(this.constructorArgTypes) :
proxyClass.getDeclaredConstructor());
//设置构造器的可访问属性,即ctor.setAccessible(true)
ReflectionUtils.makeAccessible(ctor);
//根据是否手动设置了构造器参数调用相关反射方法创建代理类的实例
proxyInstance = (this.constructorArgs != null ?
ctor.newInstance(this.constructorArgs) : ctor.newInstance());
} catch (Throwable ex) {
throw new AopConfigException("Unable to instantiate proxy using Objenesis, " +
"and regular proxy instantiation via default constructor fails as well", ex);
}
}
//设置拦截器链,返回代理类实例
((Factory) proxyInstance).setCallbacks(callbacks);
return proxyInstance;
}
objenesis是一个小类库,可以通过绕过对象的构造函数的要求来创建某个类的对象实例,即在不调用构造函数的情况下实例化对象,当然我们也可以通过Unsafe等方法来完成。关于Objenesis:http://objenesis.org/。
这里的isWorthTrying就是判断它的worthTrying属性是否不等于Boolean.FALSE。worthTrying属性默认为null,不等于Boolean.FALSE对象,因此一般都是走这个逻辑。
/**
* SpringObjenesis的属性
*
* 是否忽略尝试通过objenesis创建实例,默认null
*/
private volatile Boolean worthTrying;
/**
* 返回此 Objenesis 实例是否值得尝试实例创建,即它是否尚未使用或已知是否有效。
*
* 如果已将配置的 Objenesis 实例化器策略标识为"完全不处理当前 JVM"
* 或者"spring.objenesis.ignore"属性已设置为"true",则此方法将返回false
*/
public boolean isWorthTrying() {
return (this.worthTrying != Boolean.FALSE);
}
我们可以通过System.setProperty设置或者在名为"spring.properties"的配置文件中添加名为"spring.objenesis.ignore"的属性并且设置值为true,来表示禁止使用objenesis实例化对象!
/**
* 创建一个新的SpringObjenesis实例,strategy为null
*/
public SpringObjenesis() {
this(null);
}
/**
* SpringObjenesis的属性
*
* 指示 Spring 忽略通过 Objenesis 来创建对象,甚至不尝试使用它。
* 这意味着所有 CGLIB AOP 代理都将通过默认无参构造函数来实例化对象
*/
public static final String IGNORE_OBJENESIS_PROPERTY_NAME = "spring.objenesis.ignore";
/**
* SpringObjenesis的构造器
*
* 通过给定的标准strategy创建一个新的SpringObjenesis实例
*/
public SpringObjenesis(InstantiatorStrategy strategy) {
this.strategy = (strategy != null ? strategy : new StdInstantiatorStrategy());
//判断"spring.objenesis.ignore"系统属性的值是否为true
//我们可以通过System.setProperty或者添加名为"spring.properties"的配置文件添加这个属性
if (SpringProperties.getFlag(SpringObjenesis.IGNORE_OBJENESIS_PROPERTY_NAME)) {
//如果该属性为ture,那么worthTrying属性设置为false,表示不会使用SpringObjenesis创建对象
this.worthTrying = Boolean.FALSE;
}
}
AspectJAwareAdvisorAutoProxyCreator的核心作用就是在目标对象创建之后判断是否需要创建代理对象以及进行代理对象的创建操作。这其中主要涉及到对于Advisors通知器的初始化和预先查找操作,在会后还会涉及到JDK和CGLIB代理的选择问题,我们需要注意的是,对于@Configuration配置类,会使用CGLIB动态代理创建代理对象,以及并不是所有实现了接口的bean都会默认采用JDK动态代理。
AspectJAwareAdvisorAutoProxyCreator自动代理创建者操作完毕,那么对于能够被代理的对象,将会基于JDK动态代理创建的或者是基于CGLIB动态代理创建一个代理对象。这个代理对象内部持有一个TargetSource 对象,默认都是SingletonTargetSource,TargetSource 内部又持有一个target对象,这个target对象,就是真正的目标对象,也就是被代理的对象,在执行目标方法时,就是通过这个代理对象反射执行的。
如果一个bean被代理了,那么返回给调用者的对象(比如注入到其他对象中的对象属性)就是代理对象。在调用方法时,都是调用代理对象的方法,并且会呗转发到不同的代理处理程序方法中,对于JDK动态代理,将会执行JdkDynamicAopProxy对象的invoke方法,对于CGLIB的动态代理,将会首先执行DynamicAdvisedInterceptor的intercept方法,这两个方法就是对于目标方法进行代理和增强的方法。
我们将Spring AOP的源码解析分为三步。到目前,我们讲解了前两步:<aop:config/>AOP配置标签的解析的源码以及AOP代理对象的创建的源码,下一篇文章,我们将讲解第三步 ,也就是具体的代理增强的源码,即这些通知方法到底是如何被调用的,它们的顺序是怎么被保证的,目标方法又是在什么时候被调用的!
相关文章:
https://spring.io/
Spring Framework 5.x 学习
Spring Framework 5.x 源码
如有需要交流,或者文章有误,请直接留言。另外希望点赞、收藏、关注,我将不间断更新各种Java学习博客!