本人本科毕业,21届毕业生,一年工作经验,简历专业技能如下,现根据简历,并根据所学知识复习准备面试。
记录日期:2022.2.10
大部分知识点只做大致介绍,具体内容根据推荐博文链接进行详细复习。
文章目录
- 框架原理 - Spring(三) 之 Spring AOP 使用AspectJAwareAdvisorAutoProxyCreator创建代理对象
-
- AspectJAwareAdvisorAutoProxyCreator创建代理对象
框架原理 - Spring(三) 之 Spring AOP 使用AspectJAwareAdvisorAutoProxyCreator创建代理对象
当前使用 Spring 版本 5.2.5.RELEASE
AspectJAwareAdvisorAutoProxyCreator创建代理对象
先来看基于XML的 <aop:config /> 标签的 AspectJAwareAdvisorAutoProxyCreator 自动代理创建者的工作原理,后面再分析其他的自动代理创建者的工作原理。
UML类图
涉及类说明
ProxyConfig
ProxyConfig,用于创建AOP代理的配置超类,定义了所有类型的代理创建者都具有的一些属性。
proxyTargetClass:如果该值为true,则proxyFactory将会使用CGLIB对目标对象进行代理,默认值为falseoptimize:标记是否对代理进行优化。启动优化通常意味着在代理对象被创建后,增强的修改将不会生效,因此默认值为false。opaque:该属性用于空值生成的代理对象是否可以强制转型为Advised,默认值为false,表示任何生成的代理对象都可以强制转换成Advised,true是不可以,可以通过Adviced查询代理对象的一些状态。exposeProxy:标记代理对象是否应该被AOP框架通过AopContext以ThreadLocal的形式暴露出去。当一个代理对象需要调用它自己的另外一个代理方法时,这个属性将非常有用。默认是是false,以避免不必要的拦截。frozen:**标记该配置是否需要被冻结,如果被冻结,将不可以修改增强的配置。**如果该值为true,那么代理对象的生成的各项信息配置完成,则不容许更改,如果ProxyFactory设置完毕,该值为true,则不能对Advice进行改动,可以优化代理对象生成的性能。默认情况下该值为false。
AopInfrastructureBean
AopInfrastructureBean,标志性接口,标志着实现该接口的子类 bean作为 Spring AOP 基础结构一部分,即使被切入点匹配,也不受自动代理控制。
Ordered
Ordered,用于排序,自动代理创建者应该在所有的后处理器执行完毕之后才执行。
ProxyProcessorSupport【基类】
ProxyProcessorSupport,具有代理处理器通用功能的基类,特别是 ClassLoader 管理和 evaluateProxyInterfaces 检查接口的方法。
public class ProxyProcessorSupport extends ProxyConfig implements Ordered, BeanClassLoaderAware, AopInfrastructureBean {
// AOP的自动代理创建器必须在所有的别的processors之后执行
private int order = Ordered.LOWEST_PRECEDENCE;
// 当然此处还是提供了方法,你可以自己set或者使用@Order来人为的改变这个顺序
public void setOrder(int order) {
this.order = order;
}
@Override
public int getOrder() {
return this.order;
}
// 这是它提供的一个最为核心的方法:这里决定了如果目标类没有实现接口直接就是Cglib代理
// 检查给定beanClass上的接口,并交给proxyFactory处理
protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) {
// 找到该类实现的所有接口
Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader());
// 标记:是否有存在合理的接口
boolean hasReasonableProxyInterface = false;
for (Class<?> ifc : targetInterfaces) {
if (!isConfigurationCallbackInterface(ifc) &&
!isInternalLanguageInterface(ifc) &&
ifc.getMethods().length > 0 // 该接口必须有方法
) {
hasReasonableProxyInterface = true;
break;
}
}
if (hasReasonableProxyInterface) {
// 不能只把合理的接口设置进去,而是都得加入进去
for (Class<?> ifc : targetInterfaces) {
proxyFactory.addInterface(ifc);
}
}
else {
// 这个很明显设置true,表示使用CGLIB的方式去创建代理
proxyFactory.setProxyTargetClass(true);
}
}
// 判断此接口类型是否属于容器去回调的类型:例举处理一些接口 初始化、销毁、自动刷新、自动关闭、Aware感知等等
protected boolean isConfigurationCallbackInterface(Class<?> ifc) {
return (InitializingBean.class == ifc ||
DisposableBean.class == ifc ||
Closeable.class == ifc ||
AutoCloseable.class == ifc ||
ObjectUtils.containsElement(ifc.getInterfaces(), Aware.class));
}
// 是否是如下通用的接口。若实现的是这些接口也会排除,不认为它是实现了接口的类
protected boolean isInternalLanguageInterface(Class<?> ifc) {
return (ifc.getName().equals("groovy.lang.GroovyObject") ||
ifc.getName().endsWith(".cglib.proxy.Factory") ||
ifc.getName().endsWith(".bytebuddy.MockAccess"));
}
}
AbstractAutoProxyCreator【核心】
AbstractAutoProxyCreator,同它的命名一样,是自动代理创建者的抽象实现,同时实现了 SmartInstantiationAwareBeanPostProcessor 等后处理器接口,因此将会在bean创建过程中使用AOP代理包装每一个符合条件的bean。这是Spring AOP的核心类。
为了实现自动创建代理,它在继承
ProxyProcessorSupport以外,同时实现了SmartInstantiationAwareBeanPostProcessor和BeanFactoryAware接口,与 Spring IoC 容器打通。
AbstractAdvisorAutoProxyCreator
AbstractAdvisorAutoProxyCreator,通用自动代理创建者,它基于检测每个bean的Advisor,为特殊的bean构建AOP代理。
AspectJAwareAdvisorAutoProxyCreator【重点】
AspectJAwareAdvisorAutoProxyCreator,自动代理创建者的实现之一,公开了 AspectJ 的调用上下文,当多个advice来自同一切面时,将会按照 AspectJ 的建议优先级规则对 advice 排序。
由于 AspectJAwareAdvisorAutoProxyCreator 继承了 AbstractAutoProxyCreator,而 AbstractAutoProxyCreator 实现了 SmartInstantiationAwareBeanPostProcessor,那么这个bean定义将会在IOC容器初始化的refresh方法中的 registerBeanPostProcessors 方法中被实例化并注册,这时虽然所有的bean定义都被加载了,但所有的普通bean定义并没有创建, AspectJAwareAdvisorAutoProxyCreator 将会在随后的普通bean实例创建的过程中发挥重要作用。
这些回调方法中,最重要的就是 postProcessBeforeInstantiation() 和 postProcessAfterInitialization() 方法:
- **
postProcessBeforeInstantiation()方法在Spring实例化bean之前调用,给一个返回代理对象来代替创建目标bean实例的机会。**如果返回值不为null,那么通过此扩展点获取的bean,随后还会执行postProcessAfterInitialization扩展点方法,之后直接返回该bean作为实例,否则继续向后调用,通过Spring的规则实例化、初始化bean。 - **
postProcessAfterInitialization()方法在bean已实例化、初始化完毕,并且initMethod()方法调用完毕之后回调(在Spring的规则之下),或者postProcessBeforeInstantiation()方法不返回null的时候也会回调。**此时bean实例基本创建完成,但还没有返回给依赖者,该方法可以对bean实例进行进一步改造和包装,这时就是创建代理对象的时机。
所以我们主要来分析这两个回调方法。
postProcessBeforeInstantiation()
我们来看 AbstractAutoProxyCreator 中的 postProcessBeforeInstantiation() 方法。
这个方法是在Spring实例化bean之前调用的,给一个返回代理对象来代替创建目标bean实例的机会:
- 如果返回值不为null,随后直接执行
postProcessAfterInitialization扩展点方法,不会走Spring的实例化、初始化bean的逻辑。 - 如果返回值为null,会走Spring创建对象的逻辑,最后同样会执行
postProcessAfterInitialization扩展点方法。
梳理一下 postProcessBeforeInstantiation 的代码逻辑:
- 检测该bean是否需要创建代理
- 首先判断两个条件
- 当前bean是否是Spring AOP的基础结构类(通过
isInfrastructureClass()方法判断,包括实现Advice,Pointcut,Advisor,AopInfrastructureBean接口的类) - 当前bean是否需要跳过对该类的代理(通过
shouldSkip()方法判断)
- 当前bean是否是Spring AOP的基础结构类(通过
- 通过条件判断表示不需要代理,那么存入
advisedBeans缓存中,直接返回null,后续会走Spring创建对象的逻辑,但后面的postProcessAfterInitialization方法中不会再创建代理对象。
- 首先判断两个条件
- 如果该bean可能需要创建代理
- 如果手动设置了当前目标bean的自定义的
TargetSource,那么目标bean没必要通过Spring的机制实例化,而是使用TargetSource以自定义方式实例化目标实例,进而在此处直接创建代理对象并返回,还会加入targetSourcedBeans缓存,后续不会走Spring创建对象的逻辑,后面的postProcessAfterInitialization()方法中也不会再创建代理对象。这个TargetSource相当于是目标对象的包装,从中可以获取被代理的目标对象,这样自然就不必通过Spring再创建代理目标对象了。 - 如果没有手动设置过当前目标bean的
TargetSource,那么返回null,后续会走Spring创建对象的逻辑,后面的postProcessAfterInitialization()方法中也可能会创建代理对象,这是大部分普通bean的逻辑。
- 如果手动设置了当前目标bean的自定义的
这里涉及了几个集合:
// 通过自定义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);
我们再来看 postProcessBeforeInstantiation() 代码实现:
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
// 1. 为给定beanClass和beanName生成缓存key
Object cacheKey = getCacheKey(beanClass, beanName);
// 2. 如果没设置beanName,或者targetSourcedBeans缓存不包含该beanName
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
// 2.1 如果advisedBeans缓存包含该beanName,表示已经被处理了,返回null
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
// 2.2 如果当前bean是Spring AOP的基础结构类,或者shouldSkip返回true,表示不需要代理
// shouldSkip方法,在AspectJAwareAdvisorAutoProxyCreator中被重写并初始化全部的Advisor通知器实例
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
// 2.2.1 此时将cacheKey和false存入advisedBeans缓存,表示已处理过并且无需代理
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
/* 如果我们有自定义的TargetSource,那么目标bean没必要通过Spring的机制实例化 而是使用自定义的TargetSource将以自定义方式实例化目标实例,进而在此处创建代理对象 */
// 3. 根据beanClass和beanClass获取对应的自定义TargetSource
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
// 4. 如果获取到了自定义目标源,那么需要再当前方法创建代理
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
// 加入targetSourcedBeans缓存集合,表示已处理过,后面的postProcessAfterInitialization方法中不会再创建代理
this.targetSourcedBeans.add(beanName);
}
// 5. 创建代理的逻辑,这里和后面的postProcessAfterInitialization中创建代理逻辑相同,放在最后解释
// 5.1 获取当前bean的Advisor通知器
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
// 5.2 创建代理对象
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
// 5.3 将当前cacheKey和代理对象class存入proxyTypes缓存中
this.proxyTypes.put(cacheKey, proxy.getClass());
// 5.4 返回代理对象,后续不会走Spring创建对象的逻辑
return proxy;
}
return null;
}
再提一遍,返回null,表示会走Spring创建对象的逻辑,但是后面的
postProcessAfterInitialization()方法中不会再创建代理。
getCacheKey()
在 postProcessBeforeInstantiation() 代码块 1 中。
该方法用于获取缓存的key:
- 如果具有beanName
- 如果是
FactoryBean则返回"&beanName"作为cacheKey。 - 否则直接返回beanName作为cacheKey。
- 如果是
- 如果没有beanName,则直接返回beanClass作为cacheKey。
String FACTORY_BEAN_PREFIX = "&";
protected Object getCacheKey(Class<?> beanClass, @Nullable String beanName) {
// 如果有beanName
if (StringUtils.hasLength(beanName)) {
// 是否是 FactoryBean
return (FactoryBean.class.isAssignableFrom(beanClass) ?
BeanFactory.FACTORY_BEAN_PREFIX + beanName : beanName);
}
// 如果没有beanName
else {
return beanClass;
}
}
isInfrastructureClass()
在 postProcessBeforeInstantiation() 代码块 2.2 中。
该方法用于判断当前beanClass是Spring AOP的基础结构类,是则 isInfrastructureClass() 返回true,不进行代理。默认实现是将Advice、Pointcut、Advisor、AopInfrastructureBean接口及其实现均作为AOP基础结构类。
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;
}
shouldSkip()
在 postProcessBeforeInstantiation() 代码块 2.2 中。
该方法用于判断是否需要跳过对给定bean进行的自动代理,如果不应考虑对给定bean由此后处理器进行自动代理,则子类应重写此方法以返回 true。
AbstractAutoProxyCreator中的实现
AbstractAutoProxyCreator 中的实现为如果beanName以beanCassName开头,并且以 “.ORIGINAL” 结束,那么返回true,否则返回false。
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
return AutoProxyUtils.isOriginalInstance(beanName, beanClass);
}
// AutoProxyUtils
String ORIGINAL_INSTANCE_SUFFIX = ".ORIGINAL";
static boolean isOriginalInstance(String beanName, Class<?> beanClass) {
// 如果没有设置beanName,或者beanName长度不等于(beanCassName的长度+".ORIGINAL"的长度)
if (!StringUtils.hasLength(beanName) ||
beanName.length() !=
beanClass.getName().length() + AutowireCapableBeanFactory.ORIGINAL_INSTANCE_SUFFIX.length()) {
// 那么返回false,表示不跳过
return false;
}
// 如果beanName以beanCassName开始,并且以.ORIGINAL结束,那么返回true
return (beanName.startsWith(beanClass.getName()) &&
beanName.endsWith(AutowireCapableBeanFactory.ORIGINAL_INSTANCE_SUFFIX));
}
AspectJAwareAdvisorAutoProxyCreator中的实现
AspectJAwareAdvisorAutoProxyCreator 子类重写了该方法,将会通过 findCandidateAdvisors() 方法查找beanFactory中的所有Advisor类型的通知器bean定义并且初始化(这个方法在其他地方也会调用),如果存在 AspectJPointcutAdvisor 类型的通知器实例,并且beanName等于aspectName,即表示当前的bean属于这个通知器的切面方法类bean,那么不应该拦截切面方法类的方法,直接返回true,表示跳过。否则在最后会才会调用父类的逻辑。
前面解析 <aop:config /> 标签时,<aop:advisor /> 标签的 DefaultBeanFactoryPointcutAdvisor,<aop:declare-parents /> 标签的 DeclareParentsAdvisor,通知标签的 AspectJPointcutAdvisor,它们都属于 Advisor,也就是通知器,通常一个切入点和一个通知方法就组成通知器。
另外,如果是 AnnotationAwareAspectJAutoProxyCreator 类型的自动代理创建者,还会初始化所有基于注解的通知器。
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
// 查找bean工厂的所有Advisor类型的通知器bean定义并且初始化,返回Advisor实例的集合。
List<Advisor> candidateAdvisors = findCandidateAdvisors();
for (Advisor advisor : candidateAdvisors) {
// 如果存在AspectJPointcutAdvisor类型的通知器实例,并且当前的bean属于这个通知器的切面方法类bean
// 那么不应该拦截切面方法类的方法,直接返回true,表示跳过
if (advisor instanceof AspectJPointcutAdvisor &&
((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
return true;
}
}
// 否则调用父类AbstractAutoProxyCreator的方法
return super.shouldSkip(beanClass, beanName);
}
getCustomTargetSource()
在 postProcessBeforeInstantiation() 代码块 3 中。
该方法用于获取当前bean的自定义目标源 TargetSource。
每个代理对象保存了一个 TargetSource 对象,这个 TargetSource 对象内部封装了一个AOP的目标对象也就是被代理对象,通过 getTarget() 方法可获取目标对象,然后就能通过目标对象调用被代理的原始方法了。如果我们配置没有某个类型的 TargetSource (普通类默认都没有配置),那么这个目标对象将通过Spring来初始化,并且将采用默认的 SingletonTargetSource 目标源,而如果我们此前就自定义了 TargetSource,那么就不必执行Spring初始化bean的逻辑。
// 自定义的TargetSourceCreator数组,通过setCustomTargetSourceCreators方法初始化,默认为null
private TargetSourceCreator[] customTargetSourceCreators;
// bean工厂,通过BeanFactoryAware回调设置
private BeanFactory beanFactory;
protected TargetSource getCustomTargetSource(Class<?> beanClass, String beanName) {
// 如果customTargetSourceCreators不为null
// 并且beanFactory不为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);
// 如果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;
}
postProcessAfterInitialization()
该回调方法是在bean已实例化、初始化完毕,并且 initMethod() 方法调用完毕之后回调或者在前面的 postProcessBeforeInstantiation() 方法的返回值不为null时回调。
该方法也是在父类 AbstractAutoProxyCreator 中实现的,可以对已创建的原始bean实例进行进一步改造和包装,大部分的代理对象的创建也都在该方法中完成的,因此这个方法可以说是Spring AOP的核心方法。
// 早期代理引用缓存,key为缓存key,value为bean实例
private final Map<Object, Object> earlyProxyReferences = new ConcurrentHashMap<>(16);
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
// 获取缓存key
Object cacheKey = getCacheKey(bean.getClass(), beanName);
// 如果earlyProxyReferences的缓存移除该cacheKey之后的value不等于当前bean,表示当前bean可能需要被代理
// 如果相等,表示此前已经对这个bean已经在getEarlyBeanReference方法中调用过了wrapIfNecessary方法
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
// 调用wrapIfNecessary方法,如有必要,对目标对象进行代理包装
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
earlyProxyReferences 是早期代理引用缓存,其中的数据是在 getEarlyBeanReference() 方法被调用的时候存入进去的。
this.earlyProxyReferences.remove(cacheKey) != bean 如果相等,表示此前已经对这个bean已经在 getEarlyBeanReference() 方法中调用过了 wrapIfNecessary() 方法,这个判断就是为了保证对同一个bean的同一次创建过程中, wrapIfNecessary() 方法只被调用一次。
getEarlyBeanReference()方法用于获取早期bean的实例,此时bean实例还没有被初始化,该方法用于解决循环引用问题,在Spring IOC源码的 finishBeanFactoryInitialization() 下 docreateBean() 下中引用过,这里稍微提一下:
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
// 1. mbd不是合成 && 存在InstantiationAwareBeanPostProcessors
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
// 2. 允许SmartInstantiationAwareBeanPostProcessor调用getEarlyBeanReference返回指定bean的早期引用
exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
}
}
// 3. 返回要作为bean引用公开的对象,如果没有SmartInstantiationAwareBeanPostProcessor修改,则返回的是入参的bean对象本身
return exposedObject;
}
默认情况下其他后处理器在该方法是一个空实现,但是现在增加了AOP功能之后新添加了一个 AbstractAutoProxyCreator 后处理器,它就重写了 getEarlyBeanReference 方法,用于创建代理对象:
public Object getEarlyBeanReference(Object bean, String beanName) {
// 获取缓存key
Object cacheKey = getCacheKey(bean.getClass(), beanName);
// 将缓存key和当前bean实例存入earlyProxyReferences缓存中
this.earlyProxyReferences.put(cacheKey, bean);
// 调用wrapIfNecessary方法尝试获取代理对象还是返回原始对象
return wrapIfNecessary(bean, beanName, cacheKey);
}
wrapIfNecessary()
调用了该方法,说明当前bean对象有资格被代理,那么包装给定的bean类,创建并返回代理对象。
这里涉及了几个集合:
// 通过自定义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);
// 表示"不进行代理"的返回值便捷常量
protected static final Object[] DO_NOT_PROXY = null;
然后我们来看一下 wrapIfNecessary() 的具体实现:
这里的大部分代码类似 postProcessBeforeInstantiation() 中的实现,也只要关注两个核心方法。
getAdvicesAndAdvisorsForBean(),获取当前bean可用的Advisor通知器调用链集合。createProxy(),使用默认的SingletonTargetSource包装目标对象,并且通过JDK或者CGLIB创建代理对象。
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 如果targetSourcedBeans缓存中包含该beanName,表示已通过TargetSource创建了代理,直接返回原始bean实例
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
// 如果advisedBeans缓存中包含该cacheKey,并且value为false,表示不需要代理,直接返回原始bean实例
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
// 如果当前bean是Spring AOP的基础结构类,或者shouldSkip返回true,表示不需要代理,直接返回原始bean实例
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,表示不需要创建代理
this.advisedBeans.put(cacheKey, Boolean.FALSE);
// 返回原始bean实例
return bean;
}
getAdvicesAndAdvisorsForBean()【重点】
在 postProcessBeforeInstantiation 和 postProcessAfterInitialization 中的 wrapIfNecessary() 都使用到的第一个核心方法。
该方法用于获取当前bean可用的 Advisor 通知器,该方法由子类实现。
在解析<aop:config /> 标签时,<aop:advisor /> 标签的 DefaultBeanFactoryPointcutAdvisor ,<aop:declare-parents /> 标签的 DeclareParentsAdvisor ,通知标签的 AspectJPointcutAdvisor ,他们都属于 Advisor 类型,也就是通知器,通常一个切入点和一个通知方法就组成通知器。
来看 AbstractAdvisorAutoProxyCreator 中的实现:
可以看到,内部委托的 findEligibleAdvisors() 方法进行查找,如果返回空集合,那么最终返回null。
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通知器集合。
梳理一下 findEligibleAdvisors 的代码逻辑:
findCandidateAdvisors方法,查找所有候选Advisors链(集合),子类AnnotationAwareAspectJAutoProxyCreator重写了该方法。findAdvisorsThatCanApply方法,根据候选的Advisors链查找可以自动代理此类的所有符合条件的Advisors链(集合)。extendAdvisors扩展方法,在Advisors链的头部添加一个特殊的Advisor,用于暴露MethodInvocation,子类AspectJAwareAdvisorAutoProxyCreator重写了该方法。sortAdvisors方法,默认使用AnnotationAwareOrderComparator比较器对剩下的Advisors链(集合)进行排序,返回排序后的集合。子类AspectJAwareAdvisorAutoProxyCreator重写了该方法,子类AnnotationAwareAspectJAutoProxyCreator也会调用重写的方法,使用AspectJPrecedenceComparator比较器进行排序。AnnotationAwareOrderComparator比较器支持支持Ordered、PriorityOrdered接口,以及@Order、@Priority注解的排序。排序规则是order值越小排序越靠前,优先级越高,没有order值则默认排在尾部,优先级最低。
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 1. 查找所有候选Advisors链
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 2. 查找可以自动代理此类的所有符合条件的Advisors链
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
// 3. 扩展Advisors链的钩子方法,子类可重写该方法添加新的Advisor,或者对已存在的Advisor进行操作
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
// 4. 对Advisors链进行排序,保证调用顺序
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
1. findCandidateAdvisors()
在 findEligibleAdvisors 代码块 1 中。
该方法查找候选Advisors是通过 advisorRetrievalHelper 的 findAdvisorBeans 方法查找的。
advisorRetrievalHelper 是Advisor辅助检索器,在 BeanFactoryAware 接口回调的时候被初始化,类型为 BeanFactoryAdvisorRetrievalHelperAdapter 。
protected List<Advisor> findCandidateAdvisors() {
Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
return this.advisorRetrievalHelper.findAdvisorBeans();
}
findAdvisorBeans()
该方法查找候选Advisors,实际上就是将beanFactory中全部的Advisor类型的bean定义找到并构建实例,随后返回即可。
核心方法是 beanNamesForTypeIncludingAncestors 和 getBean 方法。
// 缓存的已找到的Advisor的beanName数组
private volatile String[] cachedAdvisorBeanNames;
public List<Advisor> findAdvisorBeans() {
// 获取已找到的Advisor的beanName数组
String[] advisorNames = this.cachedAdvisorBeanNames;
// 如果为null,表示没有缓存
if (advisorNames == null) {
// 获取全部Advisor类型的beanName数组
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
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集合中
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;
}
isEligibleBean()
该方法根据通知器的beanName判断通知器bean是否合格,如果合格才能算作候选Advisor。
该方法在 BeanFactoryAdvisorRetrievalHelper 中默认返回true。
protected boolean isEligibleBean(String beanName) {
return true;
}
被子类 BeanFactoryAdvisorRetrievalHelperAdapter 重写,继而调用 AbstractAdvisorAutoProxyCreator 的 isEligibleAdvisorBean() 方法判断,AbstractAdvisorAutoProxyCreator 的 isEligibleAdvisorBean() 方法同样默认返回true。
protected boolean isEligibleBean(String beanName) {
return AbstractAdvisorAutoProxyCreator.this.isEligibleAdvisorBean(beanName);
}
protected boolean isEligibleAdvisorBean(String beanName) {
return true;
}
isEligibleAdvisorBean 被子类 DefaultAdvisorAutoProxyCreator 和 InfrastructureAdvisorAutoProxyCreator 重写。
而 AspectJAwareAdvisorAutoProxyCreator 和 AnnotationAwareAspectJAutoProxyCreator 则没有重写。
因此该方法主要是 AspectJAwareAdvisorAutoProxyCreator 和 AnnotationAwareAspectJAutoProxyCreator 这两个自动代理创建者会用到,而 AspectJAwareAdvisorAutoProxyCreator 和 AnnotationAwareAspectJAutoProxyCreator 这两个自动代理创建者默认始终返回true。
2. findAdvisorsThatCanApply()
在 findEligibleAdvisors 代码块 2 中。
该方法搜索给定的候选Advisors,查找可应用于指定bean的所有Advisors集合。
实际上是委托给 AopUtils 的同名不同参数的方法进行调用。
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);
}
}
看一下 AopUtils.findAdvisorsThatCanApply 的代码逻辑:
- 如果Advisor通知器属于引介增强,比如
<aop:declare-parents />标签的DeclareParentsAdvisor:- 那么判断目标的beanClass的路径是否包含在当前引介增强的类路径中,也就是否匹配
types-matching属性,如果在增强类路径中,那么表示当前Advisor符合要求。
- 那么判断目标的beanClass的路径是否包含在当前引介增强的类路径中,也就是否匹配
- 如果Advisor通知器属于切入点增强,比如
<aop:advisor />标签的DefaultBeanFactoryPointcutAdvisor和各种通知标签的AspectJPointcutAdvisor:- 首先匹配目标类的类路径是否满足内部的execution切入点表达式,如果满足,那么进行第二个匹配,如果不满足,那么表示当前Advisor不符合要求。
- 匹配目标类的方法是否至少存在一个方法满足内部的execution切入点表达式,如果存在,那么表示当前Advisor符合要求,否则表示当前Advisor不符合要求。
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
// 1. 如果候选Advisors列表示空的,那么直接返回这个空列表
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
// 合格的Advisors列表
List<Advisor> eligibleAdvisors = new ArrayList<>();
// 处理引介增强,即<aop:declare-parents/>标签
// 子类AnnotationAwareAspectJAutoProxyCreator还会处理@DeclareParents注解
// 2. 遍历候选列表
for (Advisor candidate : candidateAdvisors) {
// 2.1 如果属于IntroductionAdvisor并且可以增强这个类
// tip : 这里的两个参数的canApply方法最终调用下面三个参数的canApply方法,第三个参数为false
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
// 添加当前Advisor到eligibleAdvisors集合
eligibleAdvisors.add(candidate);
}
}
// 是否存在引介增强
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
// 3. 再次遍历候选列表
for (Advisor candidate : candidateAdvisors) {
// 3.1 如果属于引介增强,表示已经处理过了,跳过
if (candidate instanceof IntroductionAdvisor) {
// already processed
continue;
}
// 3.2 对其他的Advisor同样调用canApply方法判断,第三个参数为此前判断的是否存在引介增强,一般都是false
if (canApply(candidate, clazz, hasIntroductions)) {
// 当前Advisor加入eligibleAdvisors集合
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
canApply()
在 AopUtils.findAdvisorsThatCanApply 方法中的 2.1 和 3.2 中。
该方法用于判断给定的advisor是否可以增强给定的class,简单的说就是检查class否符合advisor中的切入点表达式规则。
两参数的 canApply 最终会调用三参数的 canApply,第三个参数默认为false:
public static boolean canApply(Advisor advisor, Class<?> targetClass) {
return canApply(advisor, targetClass, false);
}
我们再来看三参数的 canApply:
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
// 如果当前advisor属于引介增强
// 比如<aop:declare-parents/>标签的DeclareParentsAdvisor
if (advisor instanceof IntroductionAdvisor) {
// 判断目标的beanClass的路径是否包含在当前引介增强的类路径中,也就是是否匹配types-matching属性
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
// 如果当前advisor属于切入点增强
// 比如<aop:advisor/>标签的DefaultBeanFactoryPointcutAdvisor和各种通知标签的AspectJPointcutAdvisor
else if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pca = (PointcutAdvisor) advisor;
// 获取切入点通知器内部的切入点,继续判断给定的切入点能否在给定的类上适用
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
// 没有切入点,那么默认true
return true;
}
}
如果当前advisor属于引介增强,那么是由各自的子类自己实现的 matches 方法调用。
如果当前advisor属于切入点增强,我们来看一下 canApply 的实现:
该方法用来判断给定的切入点能否在给定的类上适用,简单来说就是匹配内部的切入点的execution表达式。
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;
}
// 此时表明目标的beanClass的路径包含在当前切入点的类路径中,下面进一步匹配方法
// 2. 匹配目标类的方法是否至少有一个满足切入点的execution表达式
// 获取当前切入点的方法匹配器,准备匹配方法,也就是execution表达式中定义的方法
MethodMatcher methodMatcher = pc.getMethodMatcher();
// 如果匹配器是匹配所有方法,那么直接返回true
if (methodMatcher == MethodMatcher.TRUE) {
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;
}
3. extendAdvisors()
这个方法是用于扩展Advisors链的钩子方法,子类可重写该方法添加新的Advisor,或者对已存在的Advisor进行操作。
protected void extendAdvisors(List<Advisor> candidateAdvisors) {
}
子类 AnnotationAwareAspectJAutoProxyCreator 重写了该方法,子类 AspectJAwareAdvisorAutoProxyCreator 继承了 AnnotationAwareAspectJAutoProxyCreator。
@Override
protected void extendAdvisors(List<Advisor> candidateAdvisors) {
AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(candidateAdvisors);
}
实际上是调用了 AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(candidateAdvisors) 来添加特殊的 Advisors。
梳理一下 makeAdvisorChainAspectJCapableIfNecessary 的代码逻辑:
添加一个特殊的Advisor到Advisors链头部,使用 AspectJ 切入点表达式和使用 AspectJ 样式的Advice时都需要添加,添加的是 ExposeInvocationInterceptor.ADVISOR ,实际类型是一个 DefaultPointcutAdvisor 类型的单例实例,它内部保存了 ExposeInvocationInterceptor 拦截器的单例实例,当进行拦截时Advisors链的第一个方法就是调用该拦截器的 invoke 方法。
public static final ExposeInvocationInterceptor INSTANCE = new ExposeInvocationInterceptor();
public static final Advisor ADVISOR = new DefaultPointcutAdvisor(INSTANCE) {
@Override
public String toString() {
return ExposeInvocationInterceptor.class.getName() +".ADVISOR";
}
};
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 的 invoke 方法:
这个拦截器的作用就是暴露当前 MethodInvocation,实际操作就是将当前 MethodInvocation 存入一个 ThreadLocal 本地线程变量中,后续的拦截器可以直接通过 ExposeInvocationInterceptor.currentInvocation() 静态方法快速获取当前的 MethodInvocation 。
private static final ThreadLocal<MethodInvocation> invocation =
new NamedThreadLocal<>("Current AOP method invocation");
public Object invoke(MethodInvocation mi) throws Throwable {
MethodInvocation oldInvocation = invocation.get();
invocation.set(mi);
try {
return mi.proceed();
}
finally {
invocation.set(oldInvocation);
}
}
4. sortAdvisors()
在 findEligibleAdvisors 代码块的 4 中。
实际上调用的 AnnotationAwareOrderComparator.sort(advisors) 进行排序,默认采用的是 AnnotationAwareOrderComparator 比较器。
protected List<Advisor> sortAdvisors(List<Advisor> advisors) {
AnnotationAwareOrderComparator.sort(advisors);
return advisors;
}
该比较器支持 Ordered、PriorityOrdered 接口,以及 @Order、@Priority 注解的排序,比较优先级为 PriorityOrdered > Ordered > @Ordered > @Priority 。
排序规则是 order值 越小排序越靠前,优先级越高,没有 order值 则默认排在尾部,优先级最低。可以通过 <aop:aspect /> 标签的order属性为一批Advisor设置 order值。order值相同的Advisor之间的顺序不能确定,即偏序排序。
具体的排序实现就不看了,在父类
OrderComparator中重写的compare方法中调用doCompare方法。
public static final AnnotationAwareOrderComparator INSTANCE = new AnnotationAwareOrderComparator();
public static void sort(List<?> list) {
if (list.size() > 1) {
list.sort(INSTANCE);
}
}
sortAdvisors() 在子类 AspectJAwareAdvisorAutoProxyCreator 被重写,这里使用的是 AspectJPrecedenceComparator 比较器。
我们来看一下 sortAdvisors 的代码逻辑:
- 首先通过
AnnotationAwareOrderComparator来排序。 PartialOrder.sort方法涉及到偏序排序和图形映射。
子类AnnotationAwareAspectJAutoProxyCreator也会调用该重写的方法。
private static final Comparator<Advisor> DEFAULT_PRECEDENCE_COMPARATOR = new AspectJPrecedenceComparator();
@Override
protected List<Advisor> sortAdvisors(List<Advisor> advisors) {
List<PartiallyComparableAdvisorHolder> partiallyComparableAdvisors = new ArrayList<>(advisors.size());
// Advisor封装成为PartiallyComparableAdvisorHolder对象,它是AspectJAwareAdvisorAutoProxyCreator的内部类
// 并加入到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);
}
}
我们看一下 AspectJPrecedenceComparator 内部调用:
- 对于比较结果返回0的两个Advisor,不是表示相等,而是它们不能通过这个规则比较,比如它们的
order值相等或者都为null,那么继续尝试采用其他规则比较。 - 通过equals方法比较它们的aspectName属性,也就是所属的
<aop:aspect />的ref值,如果aspectName属性值不相等,那么比较结束,它们的顺序不能确定,偏序排序。 - 如果
aspectName属性值相等,那么最后比较它们的declarationOrder属性,这个属性表示“声明顺序”,值就是当前的Advisor对应的标签在外部<aop:aspect/>标签中的所有节点的定义顺序由上而下的索引值,该值不能手动设置,只能是在编写XML文件的时候注意顺序。
declarationOrder的比较排序规则比较复杂。如果declarationOrder值还是相等,那么它们的顺序同样不能确定,不同种类的通知之间的顺序也无法通过比较确定出来(这是在后面拦截方法的时候才会处理的),也是偏序排序。
private static final int HIGHER_PRECEDENCE = -1;
private static final int SAME_PRECEDENCE = 0;
private static final int LOWER_PRECEDENCE = 1;
private final Comparator<? super Advisor> advisorComparator;
public AspectJPrecedenceComparator() {
// 内部保存了一份 AnnotationAwareOrderComparator 的实例
this.advisorComparator = AnnotationAwareOrderComparator.INSTANCE;
}
@Override
public int compare(Advisor o1, Advisor o2) {
// 首先通过AnnotationAwareOrderComparator排序
int advisorPrecedence = this.advisorComparator.compare(o1, o2);
// 返回为0的情况下,再来比较aspectName
if (advisorPrecedence == SAME_PRECEDENCE && declaredInSameAspect(o1, o2)) {
advisorPrecedence = comparePrecedenceWithinAspect(o1, o2);
}
return advisorPrecedence;
}
// 比较引用是否相同
private boolean declaredInSameAspect(Advisor advisor1, Advisor advisor2) {
return (hasAspectName(advisor1) && hasAspectName(advisor2) &&
// 通过equals方法比较它们的aspectName属性,也就是所属的< aop:aspect/>的ref值
// 如果aspectName属性值不相等,那么比较结束,它们的顺序不能确定,偏序排序
getAspectName(advisor1).equals(getAspectName(advisor2)));
}
private int comparePrecedenceWithinAspect(Advisor advisor1, Advisor advisor2) {
// 声明排序
boolean oneOrOtherIsAfterAdvice =
(AspectJAopUtils.isAfterAdvice(advisor1) || AspectJAopUtils.isAfterAdvice(advisor2));
// 比较DeclarationOrder值
int adviceDeclarationOrderDelta =
getAspectDeclarationOrder(advisor1) - getAspectDeclarationOrder(advisor2);
// 先比较声明位置,再比较DeclarationOrder值
if (oneOrOtherIsAfterAdvice) {
// the advice declared last has higher precedence
if (adviceDeclarationOrderDelta < 0) {
// advice1 was declared before advice2
// so advice1 has lower precedence
return LOWER_PRECEDENCE;
}
else if (adviceDeclarationOrderDelta == 0) {
return SAME_PRECEDENCE;
}
else {
return HIGHER_PRECEDENCE;
}
}
else {
// the advice declared first has higher precedence
if (adviceDeclarationOrderDelta < 0) {
// advice1 was declared before advice2
// so advice1 has higher precedence
return HIGHER_PRECEDENCE;
}
else if (adviceDeclarationOrderDelta == 0) {
return SAME_PRECEDENCE;
}
else {
return LOWER_PRECEDENCE;
}
}
}
createProxy()【重点】
该方法用于为给定的 bean 创建 AOP 代理。这一步会选择到底是通过 JDK代理 创建还是通过 CGLIB代理 创建。
// 指示是否应冻结代理并且无法更改任何advice
private boolean freezeProxy = false;
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
// 1. 公开指定 bean 的给定目标类,也就是保存其原来的类型
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
// 2. 新建一个ProxyFactory代理工厂对象,用于创建代理
ProxyFactory proxyFactory = new ProxyFactory();
// 3. 从当前AbstractAutoProxyCreator拷贝属性,实际上就是拷贝ProxyConfig内部的几个属性
proxyFactory.copyFrom(this);
// 4. 检查proxyTargetClass属性,判断是走哪种代理方式,true时强制CGLIB;false时尝试JDK,不行再CGLIB
if (proxyFactory.isProxyTargetClass()) {
// 4.1 显式处理JDK代理目标(用于介绍建议场景)
// 判断是否是代理类
if (Proxy.isProxyClass(beanClass)) {
// 必须允许介绍;不能只将接口设置为代理的接口
for (Class<?> ifc : beanClass.getInterfaces()) {
proxyFactory.addInterface(ifc);
}
}
}
else {
// 4.2 继续检查当前bean对应的bean定义的PRESERVE_TARGET_CLASS_ATTRIBUTE属性
// 如果存在该属性并且为true,那么就强制走CGLIB
if (shouldProxyTargetClass(beanClass, beanName)) {
// 那么将proxyTargetClass改为true,表示还是走基于类的CGLIB代理
proxyFactory.setProxyTargetClass(true);
}
else {
// 4.3 评估需要代理的接口,添加到proxyFactory中,如果没有至少一个合理的代理接口,那么仍然会走基于类的CGLIB代理
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// 5. 构建给定 bean 的advisors拦截器链,包括特定的拦截器以及公共拦截器,并且将这些都适配成Advisor接口体系
// 比如MethodInterceptor方法拦截器将被包装成为一个DefaultPointcutAdvisor
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
// 5.1 advisors添加到proxyFactory的advisors属性集合中
proxyFactory.addAdvisors(advisors);
// 5.2 targetSource添加到proxyFactory的targetSource属性中,通过此可以获取源目标对象
proxyFactory.setTargetSource(targetSource);
// 5.3 继续自定义ProxyFactory钩子方法,默认空实现,留给子类实现
customizeProxyFactory(proxyFactory);
// 5.4 设置frozen属性,表示指示是否应冻结代理并且无法更改任何advice,默认false
proxyFactory.setFrozen(this.freezeProxy);
// 6. 判断是否已对advisors进行ClassFilter筛选
// 如果为true,表示已筛选,那么后续在生成 AOP 调用的advisors链时跳过 ClassFilter 检查
// 默认为false
if (advisorsPreFiltered()) {
// 设置proxyFactory的preFiltered属性为true,表示已筛选
proxyFactory.setPreFiltered(true);
}
ClassLoader classLoader = getProxyClassLoader();
// 7. 如果bean没有在重写类加载器中本地加载,则使用原始类加载器
if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) {
classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();
}
// 8. 通过proxyFactory获取代理对象
return proxyFactory.getProxy(classLoader);
}
exposeTargetClass()
在 createProxy 代码块的 1 中。
该方法主要用来公开要代理的指定 bean 的原始类。
实际上就是存入当前bean对应的 ORIGINAL_TARGET_CLASS_ATTRIBUTE 属性中,也就是 "org.springframework.aop.framework.autoproxy.AutoProxyUtils.originalTargetClass" 属性。
这个“属性”并不是存储在
BeanDefinition中,而是存放在BeanDefinition实际类型的父类AttributeAccessorSupport的attributes缓存中,该缓存属于对象级别,每一个bean定义都有自己的attributes缓存,因此不会共享。
// "org.springframework.aop.framework.autoproxy.AutoProxyUtils.originalTargetClass"
public static final String ORIGINAL_TARGET_CLASS_ATTRIBUTE =
Conventions.getQualifiedAttributeName(AutoProxyUtils.class, "originalTargetClass");
public static String getQualifiedAttributeName(Class<?> enclosingClass, String attributeName) {
Assert.notNull(enclosingClass, "'enclosingClass' must not be null");
Assert.notNull(attributeName, "'attributeName' must not be null");
return enclosingClass.getName() + '.' + attributeName;
}
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);
}
}
isProxyTargetClass()
在 createProxy 代码块的 4 中。
proxyTargetClass 值,是 ProxyConfig 中的参数。
- 为
true时,那么就强制走CGLIB代理。 - 为
false时,先尝试走JDK代理,不行再走CGLIB代理。
proxyTargetClass 值的设置方式:
- 通过
<aop:aspectj-autoproxy />、<aop:config />标签的proxy-target-class的属性设置,默认false。 - 通过
@EnableAspectJAutoProxy注解的proxyTargetClass属性设置,默认false。
用图表来解释如下:
| proxyTargetClass | 目标对象特征 | 代理效果 |
|---|---|---|
| true | 目标对象实现了接口 | 使用CGLIB代理机制 |
| true | 目标对象没有接口(只有实现类) | 使用CGLIB代理机制 |
| false | 目标对象实现了接口 | 使用JDK动态代理机制(代理所有实现了的接口) |
| false | 目标对象没有接口(只有实现类) | 使用CGLIB代理机制 |
shouldProxyTargetClass()
在 createProxy 代码块的 4.2 中。
该方法用来判断是否应该使用CGLIB代理。
在上述代码中,进入此代码的前提为获取的 proxyTargetClass 属性为false。
检查当前bean对应的bean定义的 PRESERVE_TARGET_CLASS_ATTRIBUTE 属性,即 "org.springframework.aop.framework.autoproxy.AutoProxyUtils.preserveTargetClass" 属性,如果存在该属性,并且值为true。那么仍然需要使用基于类的代理,即 CGLIB代理 。
protected boolean shouldProxyTargetClass(Class<?> beanClass, @Nullable String beanName) {
return (this.beanFactory instanceof ConfigurableListableBeanFactory &&
AutoProxyUtils.shouldProxyTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName));
}
// "org.springframework.aop.framework.autoproxy.AutoProxyUtils.preserveTargetClass"
public static final String PRESERVE_TARGET_CLASS_ATTRIBUTE =
Conventions.getQualifiedAttributeName(AutoProxyUtils.class, "preserveTargetClass");
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时,走CGLIB代理
return Boolean.TRUE.equals(bd.getAttribute(PRESERVE_TARGET_CLASS_ATTRIBUTE));
}
return false;
}
evaluateProxyInterfaces()
在 createProxy 代码块的 4.3 中。
该方法用于继续检查接口。
在上述代码中,进入此代码的前提为获取的 proxyTargetClass 属性为false,并且 shouldProxyTargetClass 方法也返回false。
梳理一下 evaluateProxyInterfaces 的代码逻辑:
- 检查给定 bean 类上的接口。
- 如果存在至少一个合理的接口,那么将所有接口都设置到
ProxyFactory的interfaces集合中 - 如果没有筛选到至少一个合理的代理接口,仍然退回到基于类的
CGLIB代理,将proxyTargetClass改为 true。
- 如果存在至少一个合理的接口,那么将所有接口都设置到
合理的代理接口三个条件:
- 如果当前接口不是一个容器回调接口(
isConfigurationCallbackInterface返回false) - 并且当前接口不是内部语言接口(
isInternalLanguageInterface返回false) - 接口方法个数至少为1个(不是标志性接口)
protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) {
// 获取当前类实现的所有接口的class数组
Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader());
// 是否具有合理的代理的接口,默认false
boolean hasReasonableProxyInterface = false;
// 遍历所有接口的class数组
for (Class<?> ifc : targetInterfaces) {
// 满足三个条件
// 如果当前接口不是一个容器回调接口
if (!isConfigurationCallbackInterface(ifc) &&
// 当前接口不是内部语言接口
!isInternalLanguageInterface(ifc) &&
// 接口方法个数至少为1个
ifc.getMethods().length > 0) {
// 标明当前接口为合理的代理接口,设置为true,并结束循环
hasReasonableProxyInterface = true;
break;
}
}
// 如果具有合理的代理的接口
if (hasReasonableProxyInterface) {
// 再次遍历全部接口class数组,将接口存入proxyFactory的interfaces集合中
for (Class<?> ifc : targetInterfaces) {
proxyFactory.addInterface(ifc);
}
}
else {
// 如果没有合理的代理的接口,那么将proxyTargetClass改为true,表示还是走基于类的CGLIB代理
proxyFactory.setProxyTargetClass(true);
}
}
isConfigurationCallbackInterface()
这是三个条件中的第一个条件。
该方法用于判断给定的接口是否只是一个容器回调接口,如果是,那么将不被视为合理的代理接口,将返回true。
如果接口属于 InitializingBean 、DisposableBean、Closeable、AutoCloseable接口以及 Aware 接口包括其子接口,那么这个接口就是一个容器回调接口,将不被视为合理的代理接口。
protected boolean isConfigurationCallbackInterface(Class<?> ifc) {
return (InitializingBean.class == ifc ||
DisposableBean.class == ifc ||
Closeable.class == ifc ||
AutoCloseable.class == ifc ||
ObjectUtils.containsElement(ifc.getInterfaces(), Aware.class));
}
isInternalLanguageInterface()
这是三个条件中的第二个条件。
该方法用于判断给定的接口是否是内部语言接口,如果是,那么将不被视为合理的代理接口,将返回true。
如果接口的全路径名等于 "groovy.lang.GroovyObject",或者以 ".cglib.proxy.Factory" 结尾,或者以 ".bytebuddy.MockAccess" 结尾。那么这个接口就是一个内部语言接口,将不被视为合理的代理接口。
这种内部语言接口只能是框架内部使用,我们开发者不应该使用。
protected boolean isInternalLanguageInterface(Class<?> ifc) {
return (ifc.getName().equals("groovy.lang.GroovyObject") ||
ifc.getName().endsWith(".cglib.proxy.Factory") ||
ifc.getName().endsWith(".bytebuddy.MockAccess"));
}
customizeProxyFactory()
在 createProxy 代码块的 5.3 中。
这是一个钩子方法,用于拓展,当前版本仍是一个空实现。
getProxy()
在 createProxy 代码块的 8 中。
该方法用于通过 proxyFactory 获取代理对象,内部逻辑是先获取对应类型的 AopProxy ,然后通过 AopProxy 获取代理对象。
AopProxy 是AOP代理对象的抽象接口,提供了两个 getProxy() 方法,用于获取实际的 AopProxy 对象。
public Object getProxy(@Nullable ClassLoader classLoader) {
// 创建AopProxy,通过AOP代理获取代理对象
return createAopProxy().getProxy(classLoader);
}
1. createAopProxy()
该方法用于创建指定类型的 AopProxy,默认 AopProxyFactory 类型为 DefaultAopProxyFactory ,随后通过 DefaultAopProxyFactory 的 createAopProxy() 方法创建 AopProxy 对象。
// 默认AopProxyFactory类型为 DefaultAopProxyFactory
private AopProxyFactory aopProxyFactory;
public ProxyCreatorSupport() {
this.aopProxyFactory = new DefaultAopProxyFactory();
}
public AopProxyFactory getAopProxyFactory() {
return this.aopProxyFactory;
}
protected final synchronized AopProxy createAopProxy() {
// 如果没有激活,那么激活代理配置,只会在创建第一个 AOP 代理时激活一次
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
DefaultAopProxyFactory.createAopProxy()
在 DefaultAopProxyFactory 中实现的 createAopProxy 方法。
该方法用于根据配置类型选择创建JDK或者CGLIB类型的AopProxy并返回。
梳理一下 createAopProxy 的代码逻辑:
- 首先判断四个条件:
- 如果
NativeDetector.inNativeImage()的方法返回false,这个主要与GraalVM Native Image有关,如果想为true,需要配置System.getProperty("org.graalvm.nativeimage.imagecode")对应参数的值,只是在Spring 5.3.4 中新加的内容,如果对GraalVM Native Image有兴趣,参考一下 GraalVM Native Image介绍 - 如果
isOptimize()方法返回true,即optimize属性为true,表示CGLIB代理应该主动进行优化,默认false。 - 如果
isProxyTargetClass()方法返回true,即proxyTargetClass属性为true,表示应该使用CGLIB代理,默认false。 - 如果
hasNoUserSuppliedProxyInterfaces()方法返回true,表示没有可使用的合理的代理接口或者只有一个代理接口并且属于SpringProxy接口体系(即校验interfaces集合,这个集合就是在此前evaluateProxyInterfaces()方法中加入的接口集合)。
- 如果
- 以上四个条件满足第一个条件并且满足后面三个任意一个条件,继续判断:
- 如果要代理的目标类型是接口,或者目标类型就是Proxy类型,这两个条件满足任意一个,那么还是采用JDK代理,返回
JdkDynamicAopProxy类型的AopProxy,proxyFactory作为构造器参数。 - 两个条件都不满足,那么最终采用
CGLIB代理,返回ObjenesisCglibAopProxy类型的AopProxy,proxyFactory作为构造器参数。
- 如果要代理的目标类型是接口,或者目标类型就是Proxy类型,这两个条件满足任意一个,那么还是采用JDK代理,返回
- 上面三个条件都不满足,那么默认采用
JDK代理,返回JdkDynamicAopProxy类型的AopProxy,proxyFactory作为构造器参数。
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// 校验四个条件,具体参照上方
if (!NativeDetector.inNativeImage() &&
(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);
}
}
new JdkDynamicAopProxy(config) 创建JDK代理
新建一个基于 JDK 的 AopProxy,即 JdkDynamicAopProxy,将前面的 proxyFactory 对象赋给 advised 属性。
public static final TargetSource EMPTY_TARGET_SOURCE = EmptyTargetSource.INSTANCE;
public static final EmptyTargetSource INSTANCE = new EmptyTargetSource(null, true);
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
Assert.notNull(config, "AdvisedSupport must not be null");
if (config.getAdvisorCount() == 0 &&
config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
throw new AopConfigException("No advisors and no TargetSource specified");
}
// 1. 将config赋值给advised属性
this.advised = config;
// 2. 获取代理对象全部需要代理的接口数组,并缓存到proxiedInterfaces属性
this.proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
// 3. 查找接口中是否有接口存在equals方法或者hashCode方法,有的话分别标记equalsDefined和hashCodeDefined字段
findDefinedEqualsAndHashCodeMethods(this.proxiedInterfaces);
}
}
completeProxiedInterfaces()
在 new JdkDynamicAopProxy(config) 代码块的 2 中。
这个方法用于确定需要代理的完整接口集。
通常,会尝试在interfaces接口集的基础上追加代理三个接口 SpringProxy 、 Advised 、 DecoratingProxy。
private static final Method isSealedMethod = ClassUtils.getMethodIfAvailable(Class.class, "isSealed");
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类型
else if (Proxy.isProxyClass(targetClass)) {
// 将目标类型实现的接口加入到interfaces接口集中
advised.setInterfaces(targetClass.getInterfaces());
}
// 重新获取proxyFactory的interfaces接口集
specifiedInterfaces = advised.getProxiedInterfaces();
}
}
// 拓展集合为原来长度+3,是为了追加代理三个接口所留出的最大空位
List<Class<?>> proxiedInterfaces = new ArrayList<>(specifiedInterfaces.length + 3);
for (Class<?> ifc : specifiedInterfaces) {
// 只有非密封接口才有资格使用JDK代理(在JDK 17上)
/* 这是为了适配JDK 17的 Object.isSealed(obj) 方法 如果这个对象是密封的,则返回 true,否则返回 false 密封对象是指那些不可扩展的,且所有自身属性都不可配置且因此不可删除(但不一定是不可写)的对象。 */
if (isSealedMethod == null || Boolean.FALSE.equals(ReflectionUtils.invokeMethod(isSealedMethod, ifc))) {
// 如果接口不是密封的,则添加
proxiedInterfaces.add(ifc);
}
}
// 如果原本interfaces接口集中没有SpringProxy接口,那就追加,否则不追加
if (!advised.isInterfaceProxied(SpringProxy.class)) {
proxiedInterfaces.add(SpringProxy.class);
}
// 如果不需要阻止代理类转换为Advised类型(判断opaque属性,默认为false)
// 并且原本interfaces接口集中没有Advised接口,那就追加,否则不追加
if (!advised.isOpaque() && !advised.isInterfaceProxied(Advised.class)) {
proxiedInterfaces.add(Advised.class);
}
// 如果需要公开DecoratingProxy接口
// 并且原本interfaces接口集中没有DecoratingProxy接口,那就追加,否则不追加
if (decoratingProxy && !advised.isInterfaceProxied(DecoratingProxy.class)) {
proxiedInterfaces.add(DecoratingProxy.class);
}
// 返回类集合
return ClassUtils.toClassArray(proxiedInterfaces);
}
findDefinedEqualsAndHashCodeMethods()
在 new JdkDynamicAopProxy(config) 代码块的 3 中。
该方法用于查找传入接口集合是否存在的任何 equals 或者 hashCode 方法,并标记 JdkDynamicAopProxy 对象的相关属性:
- 如果存在
equals方法,那么equalsDefined属性设置为true。 - 如果存在
hashCode方法,那么hashCodeDefined属性设置为true。
// 接口集合中是否存在某个集合有equals方法
private boolean equalsDefined;
// 接口集合中是否存在某个集合有hashCode方法
private boolean hashCodeDefined;
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;
}
}
}
}
new ObjenesisCglibAopProxy(config) 创建CGLIB代理
新建一个基于 CGLIB 的 AopProxy ,即 ObjenesisCglibAopProxy ,将前面的 proxyFactory 对象赋给 advised 属性。后续调用 ObjenesisCglibAopProxy 对象的方法时,会调用它的 intercept() 方法。
public static final TargetSource EMPTY_TARGET_SOURCE = EmptyTargetSource.INSTANCE;
public static final EmptyTargetSource INSTANCE = new EmptyTargetSource(null, true);
class ObjenesisCglibAopProxy extends CglibAopProxy {
public ObjenesisCglibAopProxy(AdvisedSupport config) {
super(config);
}
}
class CglibAopProxy implements AopProxy, Serializable {
public CglibAopProxy(AdvisedSupport config) throws AopConfigException {
Assert.notNull(config, "AdvisedSupport must not be null");
if (config.getAdvisorCount() == 0 &&
config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
throw new AopConfigException("No advisors and no TargetSource specified");
}
this.advised = config;
this.advisedDispatcher = new AdvisedDispatcher(this.advised);
}
}
2. getProxy()
JdkDynamicAopProxy.getProxy() 获取代理对象
该方法最终是通过 Proxy.newProxyInstance 方法来创建代理对象。
在前面介绍 备战面试日记(3.3) - 设计模式.23种设计模式之结构型模式 的时候就提到过动态代理的实现,那么这个方法应该很熟悉了,这就是 JDK动态代理 获取代理对象的方式,它创建代理对象使用的类库 Proxy 来自JDK的核心 rt.jar 包。
newProxyInstance方法的参数介绍:
- 第一个参数是类加载器。
- 第二个参数就是代理类对象需要实现的接口数组。
- 第三个参数就是当前 JdkDynamicAopProxy 对象,作为调用处理程序。
当代理对象在调用方法时,方法调用被分派到调用处理程序的invoke方法,即 JdkDynamicAopProxy 对象的invoke方法,这个invoke方法定义了代理对象的额外的行为,也就是如果对原始对象和方法进行增强的逻辑。
@Override
public Object getProxy() {
return getProxy(ClassUtils.getDefaultClassLoader());
}
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
}
ObjenesisCglibAopProxy.getProxy() 获取代理对象
该方法是由父类 CglibAopProxy 实现。
该方法采用CGLIB动态代理获取代理对象,最终就是先通过创建的Enhancer增强器来获取代理类的class,随后直接通过objenesis绕过构造器创建代理类对象或者通过反射调用代理类的构造器创建代理类对象。
// ----------内部------------
// AOP配置,就是前面的proxyFactory对象
protected final AdvisedSupport advised;
private transient Map<Method, Integer> fixedInterceptorMap = Collections.emptyMap();
private transient int fixedInterceptorOffset;
// ----------内部------------
// ----------外部------------
// ClassUtils 中 Cglib类分隔符
public static final String CGLIB_CLASS_SEPARATOR = "$$";
// SpringNamingPolicy 中
public static final SpringNamingPolicy INSTANCE = new SpringNamingPolicy();
// ----------外部------------
@Override
public Object getProxy() {
return getProxy(null);
}
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
}
try {
// 1. 获取目标类
Class<?> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
// 2. 将目标类作为代理类的父类
Class<?> proxySuperClass = rootClass;
// 3. 通过判断类名是否包含"$$"来判断目标类是否同样是由CGLIB生成的类
if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
// 如果也是CGLIB生成的类
// 3.1 进一步获取目标类的父类,作为代理类的父类
proxySuperClass = rootClass.getSuperclass();
// 3.2 获取目标类的接口
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
// 3.3 加入到advised中的interfaces集合中
for (Class<?> additionalInterface : additionalInterfaces) {
this.advised.addInterface(additionalInterface);
}
}
// 4. 检验代理类的父类,并输出日志,检查给定class上的final方法,以及跨 ClassLoaders 的包可见方法,并将警告写入日志
validateClassIfNecessary(proxySuperClass, classLoader);
// 5. 创建并配置CGLIB的Enhancer增强器,CGLIB就是通过Enhancer来创建代理对象的
Enhancer enhancer = createEnhancer();
// 6. 配置Enhancer增强器
if (classLoader != null) {
// 6.1 设置类加载器
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
// 6.2 设置继承的父类为目标类型
enhancer.setSuperclass(proxySuperClass);
// 6.3 设置实现的接口
// 所以即使是通过CGLIB创建的代理类对象也是实现了接口的,至少会实现SpringProxy和Advised接口
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
// 6.4 设置类名命名策略
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
// 6.5 设置设置用于从此生成器创建字节码的策略
enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));
// 6.6.1 获取全部需要回调的拦截器链数组,其中第一个拦截器就是DynamicAdvisedInterceptor ,封装了全部增强的方法
Callback[] callbacks = getCallbacks(rootClass);
// 6.6.2 全部拦截器的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
// 6.6.3 设置回调过滤器
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
// 6.7 设置回调类型
enhancer.setCallbackTypes(types);
// 7. 根据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);
}
}
validateClassIfNecessary()
在 CglibAopProxy.getProxy() 代码块的 4 中。
校验提供的代理类的父类(通常就是目标类),并输出日志。
即检查给定class上的final方法,以及跨 ClassLoaders 的包可见方法,并将警告写入日志。
protected static final Log logger = LogFactory.getLog(CglibAopProxy.class);
// 跟踪为对final方法进行验证的类
private static final Map<Class<?>, Boolean> validatedClasses = new WeakHashMap<>();
private void validateClassIfNecessary(Class<?> proxySuperClass, @Nullable ClassLoader proxyClassLoader) {
// 检查log是否开启warn级别的日志
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();
// 如果不是static静态的并且不是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);
}
}
getCallbacks()
在 CglibAopProxy.getProxy() 代码块的 6.6.1 中。
该方法用于获取回调拦截器数组,第一个拦截器是 DynamicAdvisedInterceptor ,封装了全部增强的方法。
当进行方法调用的时候,第一个调用的也是拦截器链头部的 DynamicAdvisedInterceptor 的 intercept() 方法。
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目标源是静态的,其他目标源默认都是非静态的。
// LazyInitTargetSource实际上也会缓存,但是它是非静态的。
// 其中,大部分普通类都是SingletonTargetSource类型的目标源。
boolean isStatic = this.advised.getTargetSource().isStatic();
// 创建Aop拦截器(用于 AOP 调用),内部封装了增强方法
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
// 新建目标拦截器
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()));
}
// 目标转发器
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;
// 如果目标是静态的,建议链被冻结,
// 然后我们可以通过发送AOP调用来进行一些优化
// 使用该方法的固定链指向目标。
if (isStatic && isFrozen) {
Method[] methods = rootClass.getMethods();
Callback[] fixedCallbacks = new Callback[methods.length];
this.fixedInterceptorMap = CollectionUtils.newHashMap(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;
}
return callbacks;
}
我们可以来看一下 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) {
// Make invocation available if necessary.
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;
// 如果没有可以应用到此方法的通知(Interceptor),则直接反射调用 method.invoke(target, args)
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = methodProxy.invoke(target, argsToUse);
}
else {
// 否则,创建MethodInvocation,匹配joinPoint,调用 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);
}
}
}
createProxyClassAndInstance()
在 CglibAopProxy.getProxy() 代码块的 7 中。
**根据enhancer和callbacks生成代理类并创建代理实例。**该方法被子类 ObjenesisCglibAopProxy 重写。
我们先来看父类 CglibAopProxy 中的实现:
@Nullable
protected Object[] constructorArgs;
@Nullable
protected Class<?>[] constructorArgTypes;
protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
enhancer.setInterceptDuringConstruction(false);
enhancer.setCallbacks(callbacks);
return (this.constructorArgs != null && this.constructorArgTypes != null ?
enhancer.create(this.constructorArgTypes, this.constructorArgs) :
enhancer.create());
}
一般都是调用子类方法,所以我们来看子类 ObjenesisCglibAopProxy 的实现:
Objenesis工具:Objenesis : About
objenesis方式最后使用JDK的
ReflectionFactory.newConstructorForSerialization()实例化代理对象。这种方式创建出来的对象不会初始化类成员变量。
// Objenesis工具对象,用于生成某个类型的实例
// 它是一个小类库,可以通过绕过对象的构造函数的要求来创建某个类的对象实例
// 即在不调用构造函数的情况下实例化对象,当然也可以通过Unsafe来完成
private static final SpringObjenesis objenesis = new SpringObjenesis();
@Override
protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
// 通过Enhancer创建代理子类class
Class<?> proxyClass = enhancer.createClass();
Object proxyInstance = null;
// spring.objenesis.ignore 默认为 false,所以 objenesis.isWorthTrying() 一般为true
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) {
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;
}
isWorthTrying()
该方法用于判断是否可以尝试使用 objenesis 来生成代理类。
public boolean isWorthTrying() {
return (this.worthTrying != Boolean.FALSE);
}
而 worthTrying 的值是由它的构造参数决定,当存在配置 "spring.objenesis.ignore" 为 true 时,worthTrying 值为false。
所以 worthTrying 一般都为 true,那么 isWorthTrying() 方法一般返回 true。
public static final String IGNORE_OBJENESIS_PROPERTY_NAME = "spring.objenesis.ignore";
public SpringObjenesis(InstantiatorStrategy strategy) {
this.strategy = (strategy != null ? strategy : new StdInstantiatorStrategy());
// Evaluate the "spring.objenesis.ignore" property upfront...
if (SpringProperties.getFlag(SpringObjenesis.IGNORE_OBJENESIS_PROPERTY_NAME)) {
this.worthTrying = Boolean.FALSE;
}
}
关于 spring.objenesis.ignore 提一点可能遇到的问题:
spring.objenesis.ignore 为 true 时,表示不使用 objenesis 来生成代理类,不过一般为 flase。
这在我们显示调用代理类的属性变量时,可能会引起空指针。
原因是因为 objenesis 方式最后使用JDK的 ReflectionFactory.newConstructorForSerialization() 实例化代理对象。
这里顺便复习一下反射创建对象的方法:
java.lang.Class.newInsance()java.lang.reflect.Constructor.newInstance()sun.reflect.ReflectionFactory.newConstructorForSerialization().newInstance()
前两种初始化方式都会同时初始化类成员变量,但最后一种通过 ReflectionFactory.newConstructorForSerialization().newInstance() 实例化类,不会初始化类成员变量。
所以当我们生成代理类(即目标类的子类)时,如果直接调用代理类的属性,并且 spring.objenesis.ignore 为false时,可能会出现空指针。
解决办法就是使用方法来获取对应属性。

京公网安备 11010502036488号