引言
上期我們對AOP
核心概念及接口做了粗淺的分析,這期我們主要來探討一下代理對象
的創(chuàng)建過程凭疮。在開始之前次坡,先問自己幾個問題
Spring是如何幫我們?nèi)ミx擇合適的
Advice
的幽歼?找到了又是通過何種方式創(chuàng)建代理對象的?
好了讯嫂,現(xiàn)在我們開始分析代理對象的創(chuàng)建過程,首先兆沙,先來看一下AspectJAwareAdvisorAutoProxyCreator.class
類的繼承體系
可以看到AspectJAwareAdvisorAutoProxyCreator.class
主要實現(xiàn)了這幾個接口
-
Aware
Bean創(chuàng)建時注入一些容器屬性等 -
BeanPostProcessor
IOC 擴(kuò)展點 -
AopInfrastructureBean
標(biāo)識此類是AOP
系統(tǒng)類欧芽,不能被代理
這里我們僅需要關(guān)注BeanPostProcessor
接口的實現(xiàn),因為代理的創(chuàng)建是在BeanPostProcessor
接口的postProcessAfterInitialization
方法執(zhí)行時創(chuàng)建的葛圃,postProcessAfterInitialization
方法的具體實現(xiàn)邏輯是在抽象父類AbstractAutoProxyCreator
中實現(xiàn)的
入口
上文中提到AspectJAwareAdvisorAutoProxyCreator.class
是BeanPostProcessor
接口的實現(xiàn)千扔,現(xiàn)在就讓我們打開它的入口源碼慢慢分析
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
// 返回用做緩存的key鍵
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
// 判斷當(dāng)前的Bean是否是AOP本身的系統(tǒng)類,是的話則跳過库正,不做代理操作
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// 為該Bean找到一個合適的 advisor
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
// 返回不為空
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 創(chuàng)建代理對象
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
// 沒有找到合適的 advisor 則直接返回原始Bean
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
看完wrapIfNecessary
方法曲楚,這里就是創(chuàng)建代理對象的全過程。其實在這個方法中一共就做了兩件事情:
-
getAdvicesAndAdvisorsForBean
方法 篩選合適的Advisor
對象褥符,其實就是為當(dāng)前目標(biāo)對象找到合適的通知(Advice
) -
createProxy
方法 根據(jù)篩選到的切面(Advisor
)集合為目標(biāo)對象創(chuàng)建代理
下面我們分別對這兩件事情作分析
尋找合適的 Advisor
findEligibleAdvisors
方法是在父類AbstractAdvisorAutoProxyCreator
中龙誊,
且直接調(diào)用了findEligibleAdvisors
方法
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
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;
}
這里也是分開做了兩件事情
- 首先從Spring 容器中獲取到全部Advisors集合
- 執(zhí)行篩選邏輯,獲取符合條件的Advisors集合
找到Spring容器中全部 Advisor
這里是調(diào)用了BeanFactoryAdvisorRetrievalHelper.class
的方法去獲取到Spring 容器中全部Advisor
集合的属瓣,這里需要注意BeanFactoryAdvisorRetrievalHelper.class
類的初始化是在setBeanFactory
方法中進(jìn)行的
protected List<Advisor> findCandidateAdvisors() {
return this.advisorRetrievalHelper.findAdvisorBeans();
}
-
BeanFactoryAdvisorRetrievalHelper
的findAdvisorBeans
方法
public List<Advisor> findAdvisorBeans() {
// Determine list of advisor bean names, if not cached already.
String[] advisorNames = null;
synchronized (this) {
// 嘗試從緩存中獲取 Advisor 類型的Bean名稱
advisorNames = this.cachedAdvisorBeanNames;
//
if (advisorNames == null) {
// 從BeanFactory中獲取 Advisor 類型的全部Bean名稱集合载迄,并設(shè)置緩存
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
this.cachedAdvisorBeanNames = advisorNames;
}
}
if (advisorNames.length == 0) {
return new LinkedList<Advisor>();
}
List<Advisor> advisors = new LinkedList<Advisor>();
// 遍歷 Advisor類型 BeanName 集合
for (String name : advisorNames) {
// 判斷是否合法讯柔,這里返回都是true
if (isEligibleBean(name)) {
// 判斷該Bean是否正在創(chuàng)建中抡蛙,創(chuàng)建中則直接跳過
if (this.beanFactory.isCurrentlyInCreation(name)) {
if (logger.isDebugEnabled()) {
logger.debug("Skipping currently created advisor '" + name + "'");
}
}
else {
try {
// 根據(jù)BeanName和Advisor類型從BeanFactory中獲取Bean
advisors.add(this.beanFactory.getBean(name, Advisor.class));
}
catch (BeanCreationException ex) {
Throwable rootCause = ex.getMostSpecificCause();
if (rootCause instanceof BeanCurrentlyInCreationException) {
BeanCreationException bce = (BeanCreationException) rootCause;
if (this.beanFactory.isCurrentlyInCreation(bce.getBeanName())) {
if (logger.isDebugEnabled()) {
logger.debug("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;
}
findAdvisorBeans
方法的的目的非常明確,就是找到容器中全部的Advisor
- 先嘗試從緩存中獲取
Advisor
集合 - 緩存中不存在魂迄,則執(zhí)行獲取邏輯
- 獲取到了所有類型為
Advisor
的Bean的名稱 - 根據(jù)獲取到的BeanName獲取Bean
- 獲取到了所有類型為
為當(dāng)前Bean匹配合適的 Advisor
在以上的步驟中粗截,我們已經(jīng)拿到了容器中所有的Advisor
對象集合,也就是說我們已經(jīng)拿到了容器中所有已配置的AOP
切面捣炬。接下里的事情就是為當(dāng)前的目標(biāo)對象篩選出適合的Advisor
集合熊昌,現(xiàn)在我們開始分析AbstractAdvisorAutoProxyCreator.class
的findAdvisorsThatCanApply
方法
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
// 調(diào)用 AopUtils.findAdvisorsThatCanApply 為當(dāng)前Bean篩選合適的 Advisor
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
findAdvisorsThatCanApply
方法里調(diào)用了工具類AOPUtils
的findAdvisorsThatCanApply
方法
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new LinkedList<Advisor>();
// 先找出 IntroductionAdvisor 類型的Advisor
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
// 再從余下的Advisor中繼續(xù)匹配
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor) {
// already processed
continue;
}
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
以上代碼邏輯會先篩選出IntroductionAdvisor
類型的Advisor
,再篩選余下的其他Advisor
public static boolean canApply(Advisor advisor, Class<?> targetClass) {
return canApply(advisor, targetClass, false);
}
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
if (advisor instanceof IntroductionAdvisor) {
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
else if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pca = (PointcutAdvisor) advisor;
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
// It doesn't have a pointcut so we assume it applies.
return true;
}
}
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
// 先判斷類型是否匹配
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
// 獲取切點方法匹配器
MethodMatcher methodMatcher = pc.getMethodMatcher();
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;
}
Set<Class<?>> classes = new LinkedHashSet<Class<?>>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
classes.add(targetClass);
for (Class<?> clazz : classes) {
// 獲取當(dāng)前目標(biāo)class的所有方法
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
// 調(diào)用 methodMatcher.matches 判斷當(dāng)前方法是否匹配該切點
if ((introductionAwareMethodMatcher != null &&
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
canApply
是用于篩選核心方法湿酸,在上期分析連接點Pointcut
接口時婿屹,我們知道Pointcut
持有ClassFilter
和MethodMatcher
對象,具體的篩選邏輯就是由它們完成的推溃,至于在它們具體的macthes
方法是是如何實現(xiàn)篩選的昂利,這里我也沒有進(jìn)行過深入分析,感興趣的可以在其實現(xiàn)類AspectJExpressionPointcut.class
中繼續(xù)查看
生成代理對象
在上文的分析結(jié)束后铁坎,我們已經(jīng)篩選出來了合適的 Advisor
蜂奸,Advisor
持有Advice(通知)
,接下來的操作就是根據(jù)我們配置的Advice
為目標(biāo)對象創(chuàng)建代理對象了
protected Object createProxy(
Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
// 首先創(chuàng)建一個代理創(chuàng)建工廠類硬萍,之后的操作都是為此工廠配置屬性
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
// 判斷配置屬性proxy-target-class 是否等于False
if (!proxyFactory.isProxyTargetClass()) {
// 判斷目標(biāo) BeanDefinition是否配置preserveTargetClass 為 ture扩所,是的話配置CGLIB動態(tài)代理
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
// 設(shè)置目標(biāo)類接口到proxyFactory,如果沒有實現(xiàn)接口則使用CGLIB代理
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
// proxyFactory 設(shè)置 advisors
proxyFactory.addAdvisors(advisors);
// 設(shè)置目標(biāo)對象資源
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// 創(chuàng)建代理
return proxyFactory.getProxy(getProxyClassLoader());
創(chuàng)建代理對象前朴乖,會新建一個代理工廠創(chuàng)建類祖屏,并為此工廠類配置相關(guān)屬性助赞,例如proxy-target-class
的配置,雖然默認(rèn)配置是false
會使用JDK動態(tài)代理
袁勺,但如果沒有實現(xiàn)接口嫉拐,也會自動設(shè)置proxy-target-class
為true
使用CGLIB
創(chuàng)建代理對象
完成ProxyFactory
的配置之后,就可以通過它創(chuàng)建代理對象了
/**
* 創(chuàng)建代理對象
*/
public Object getProxy(ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
調(diào)用父類ProxyCreatorSupport
的createAopProxy
方法魁兼,獲取到代理創(chuàng)建工廠婉徘,工廠類(DefaultAopProxyFactory
)是在父類的構(gòu)造方法中創(chuàng)建的
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
// 獲取代理創(chuàng)建工廠類 (DefaultAopProxyFactory.class)創(chuàng)建代理對象
return getAopProxyFactory().createAopProxy(this);
}
最終在DefaultAopProxyFactory
工廠類createAopProxy
中創(chuàng)建代理對象
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// 這里主要是判斷 proxy-target-class 屬性是否為true蒋伦。默認(rèn)是false
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);
}
// 使用CGLIB動態(tài)代理
return new ObjenesisCglibAopProxy(config);
}
else {
// 默認(rèn)使用JDK動態(tài)打理
return new JdkDynamicAopProxy(config);
}
}
最終的代理的創(chuàng)建是在ObjenesisCglibAopProxy
或JdkDynamicAopProxy
中完成的逮光,至于更具體的創(chuàng)建邏輯,因為這一系列的源碼分析只是為了能夠?qū)?code>AOP的整體邏輯有清晰的認(rèn)識弧岳,所以這里就不做更詳細(xì)的分析了化撕。
尾言
本篇文章分析了AOP
代理創(chuàng)建的整個過程几晤,縱觀整篇文章,篇幅有限植阴,其中還有很多的點沒有詳細(xì)展開分析蟹瘾,只是粗略的分析了AOP
代理的創(chuàng)建過程,慚愧 ... 掠手。分析有誤的地方憾朴,希望大家可以指出。
Spring 系列