8. Spring 源码解析之AOP代理对象创建过程
创建代理对象过程有两个入口,AbstractAutoProxyCreator#getEarlyBeanReference
和 AbstractAutoProxyCreator#postProcessAfterInitialization
,两个调用的时机不通。
通常情况下,是通过AbstractAutoProxyCreator#postProcessAfterInitialization
来创建的代理对象。
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
在wrapIfNecessary
方法中大致分了三个步骤:
8.1 校验是否是被增强的bean
与后置处理器的前置实例化 postProcessBeforeInstantiation
做了相同的校验,如下:
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
这里不再累述。
8.1.1 获取通知和增强器
入口代码如下:
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
里面会获取适合bean的增强器,findEligibleAdvisors
方法来实现的,主要分了两部分,第一部分是获取候选的增强器,第二部分是发现可以应用的的增强器,代码如下:
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
List<Advisor> candidateAdvisors = findCandidateAdvisors();
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
其中findCandidateAdvisors()
和postProcessBeforeInstantiation
执行一样,这不过是直接从缓存中获取的,如下图:
我们主要看看怎么找到适合bean的增强器。
protected List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
// 把beanName放入ThreadLocal
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
// 这一步实现
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
在findAdvisorsThatCanApply
中循环每个Advisor,进行匹配处理,代码如下:
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor) {
// already processed
continue;
}
// 实现
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
canApply
方法做了两个准备工作:
- 获取切点的方法匹配器,用来匹配目标类的方法。
MethodMatcher methodMatcher = pc.getMethodMatcher();
- 获取所有接口类,放到一个
LinkedHashSet
中
classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(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)) {
return true;
}
}
}
这里的方法匹配器的匹配过程调用了AspectJ中的实现,具体细节不分析了。
这时候在findAdvisorsThatCanApply
方法后面调用了一个extendAdvisors(eligibleAdvisors)
方法,这个方法的目的是添加一个ExposeInvocationInterceptor.ADVISOR
作为增强器链的开始部分,转化为一个拦截器链。
AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(candidateAdvisors);
if (foundAspectJAdvice && !advisors.contains(ExposeInvocationInterceptor.ADVISOR)) {
advisors.add(0, ExposeInvocationInterceptor.ADVISOR);
return true;
}
然后把拦截器链进行排序sortAdvisors(eligibleAdvisors);
8.1.2 创建代理对象
根据返回的拦截器链的结果判断是否有代理对象specificInterceptors != DO_NOT_PROXY
有的话,去创建代理对象。
Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors,
new SingletonTargetSource(bean));
创建代理对象经历了以下几步:
-
第一步是创建一个代理工厂类
ProxyFactory
往代理工厂中添加增强器链、目标对象等。
-
第二步将拦截器链转换成增强器链
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
|- Advisor[] commonInterceptors = resolveInterceptorNames()
|- advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
- 第三步根据设置的信息,创建一个代理类
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (!IN_NATIVE_IMAGE &&
(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.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
8.2 提前暴露的代理对象
前面还说过,通过AbstractAutoProxyCreator#getEarlyBeanReference
来实现代理类的创建,具体的代理创建过程和前面一样,这里只说明以下为什么要有这样一个接口,参考例子如下:
根据bean的生命周期中介绍的,A创建实例完成后,在属性注入前,会加入三级缓存的操作,属性注入时,发现依赖B对象 ,这时候B会先创建,当B实例化完成后,属性注入时发现依赖于A,会把A的实例注入进来,会用三级缓存的ObjectFactory.getObject
方法获取A实例,这时候,就把A的代理对象注入进来,如果只使用两级缓存,这时候在A实例化后,不知道最终暴露出去的是谁,并且也不能用原来的bean实例做后面的处理动作,比如registerDisposableBeanIfNecessary(beanName, bean, mbd);
。
下面用两张图说明以下: