本文將對SpringAop中如何為AspectJ切面類創建自動代理的過程作下簡單的分析,閱讀本文前需要對AOP的Spring相關解析有所了解,具體可見Spring源碼情操陶冶-AOP之ConfigBeanDefinitionParser解析器
官方注釋
注釋內容如下
/**
* {@link org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator}
* subclass that exposes AspectJ's invocation context and understands AspectJ's rules
* for advice precedence when multiple pieces of advice come from the same aspect.
*
* @author Adrian Colyer
* @author Juergen Hoeller
* @author Ramnivas Laddad
* @since 2.0
*/
從注釋上可知此類是org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator
抽象類的繼承類,主要為AspectJ
切面服務。具體的針對如何創建代理,肯定是在父類中實現了,我們在此研究下父類。
AbstractAutoProxyCreator-AOP代理實現的抽象父類
繼承結構上為extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware
,而其中的SmartInstantiationAwareBeanPostProcessor
是beanPostProcessor接口的子類,此處注意下此接口。下面分析的內容建立在spring在實例化bean對象的時候會調用beanPostProcessor的公有接口。
AbstractAutoProxyCreator#postProcessAfterInitialization()-創建代理的入口函數
先奉上源碼內容如下
/**
* Create a proxy with the configured interceptors if the bean is
* identified as one to proxy by the subclass.
* @see #getAdvicesAndAdvisorsForBean
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
// 如果緩存中不存在則調用wrapIfNecessary()方法創建代理
if (!this.earlyProxyReferences.contains(cacheKey)) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
以上調用的是beanPostProcessor接口的postProcessAfterInitialization(Object bean,String beanName)
的方法,其一般是bean對象被實例化的最后一步操作的,此處避而不談了,我們轉而查看wrapIfNecessary()
的內部是如何操作的
AbstractAutoProxyCreator#wrapIfNecessary()-創建代理對象幫助函數
/**
* Wrap the given bean if necessary, i.e. if it is eligible for being proxied.
* @param bean the raw bean instance
* @param beanName the name of the bean
* @param cacheKey the cache key for metadata access
* @return a proxy wrapping the bean, or the raw bean instance as-is
*/
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 查看緩存是否存在此bean
if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
// Advice/Advisor/AopInfrastructureBean接口的beanClass不進行代理以及對beanName為aop內的切面名也不進行代理,此處可查看子類復寫的sholdSkip()方法
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
// 查找對代理類相關的advisor對象集合,此處就與ponit-cut表達式有關了
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
// 對相應的advisor不為空才采取代理
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 調用createProxy()方法創建真正的代理對象
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
對上述的源碼分析作下簡單的總結
首先對
Advice/Advisor/AopInfrastructureBean
接口的實現類不進行代理操作;對beanName為aspectName
的bean對象也不采取代理操作再而需要查找beanClass有幾個advisor與之相關聯,這當然與每個
Advisor
接口內的PointCut
對象對應的表達式expression
有關。只有關聯的Advisor
個數不為0,才可采取代理(此處查找Advisor關聯個數的源碼讀者可自行分析AspectJAwareAdvisorAutoProxyCreator#shouldSkip()方法)真正的代理操作是由
AbstractAutoProxyCreator#createProxy()
內部方法實現
AbstractAutoProxyCreator#createProxy()-創建真正的AOP代理
對符合條件的beanClass進行相應的代理操作,簡單看下源碼
/**
* Create an AOP proxy for the given bean.
* @param beanClass the class of the bean
* @param beanName the name of the bean
* @param specificInterceptors the set of interceptors that is
* specific to this bean (may be empty, but not null)
* @param targetSource the TargetSource for the proxy,
* already pre-configured to access the bean
* @return the AOP proxy for the bean
* @see #buildAdvisors
*/
protected Object createProxy(
Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
// 創建AOP代理工廠,拷貝相同的屬性
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
// 是否采用動態代理
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
// 查看beanClass對應的類是否含有InitializingBean.class/DisposableBean.class/Aware.class接口,無則采用靜態代理,有則采用動態代理
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// 獲得所有關聯的Advisor集合
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
for (Advisor advisor : advisors) {
proxyFactory.addAdvisor(advisor);
}
// 此處的targetSource一般為SingletonTargetSource
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
// 是否設置預過濾模式,此處針對本文為true
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
return proxyFactory.getProxy(getProxyClassLoader());
}
對以上的源碼也作下簡單的總結
采用ProxyFactory對象來創建代理對象
如果AOP沒有指定proxyTargetClass屬性,則針對beanClass含有非
InitializingBean/DisposableBean/Aware
接口的bean采用靜態代理,反之采用動態代理ProxyFactory創建代理對象前也需要設置與beanClass相關聯的advisor集合
ProxyFactory#getProxy()-最終創建代理類
public Object getProxy(ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
以上的源碼我們只需要關注createAopProxy()
方法即可,此處我們直接查看DefaultAopProxyFactory#createAopProxy()
源碼,參考如下
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
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.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
上述源碼很簡單,默認是采用JDK靜態代理,對beanClass為非接口實現類采取CGLIB動態代理
小結
循序漸進的分析的總結見以上的各部分小結,我們只需要知道AOP代理的beanClass必須有相應的
Advisor
接口與之綁定,才會創建AOP代理創建的代理類無非是JDK代理抑或是CGLIB代理,但是具體關聯的
Advisor
集合的處理邏輯見下文講解