Spring系列之Spring框架和SpringAOP整合過程分析(十二)
阿新 • • 發佈:2018-12-30
轉載請註明出處:https://blog.csdn.net/zknxx/article/details/80808447
在這篇文章中我們接著上一篇的文章說。在上一篇文章中我們提到了getAdvicesAndAdvisorsForBean這個方法,這個方法的內容是為目標物件挑選合適的Advisor類,其原始碼如下:
//targetSource 為null
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
List <Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
//如果獲取的Advisor為空的話,則直接返回DO_NOT_PROXY 返回這個值的時候 是不建立代理物件
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
protected List<Advisor> findEligibleAdvisors(Class <?> beanClass, String beanName) {
//這個方法我們在上一章中分析過了 獲取Spring容器中的所有的通知方法 封裝為Advisor集合
List<Advisor> candidateAdvisors = findCandidateAdvisors();
//這一步就是為目標物件挑選合適的Advisor 即目標物件和切點表示式相匹配
//此處的分析 請參考這裡:https://blog.csdn.net/zknxx/article/details/79735405
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
//這個方法做的事是向 上一步獲取到的Advisor中 插入ExposeInvocationInterceptor.ADVISOR 插在第一個位置
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
//排序 很複雜的實現 不說了 如果你對一個目標物件使用多個 相同型別的通知的話 請把這些通知放到不同的Aspect中,並實現Order介面或者使用Ordered註解標註順序
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
最後我們再看看目標物件的建立過程:
//specificInterceptors 上面的方法中獲取到的Advisor
//targetSource 為 new SingletonTargetSource(bean)
//將Spring容器中創建出來的bean封裝為了SingletonTargetSource
protected Object createProxy(
Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
//這裡將目標Bean的Class設定為BeanDefinition中的一個屬性
//在使用JDK動態代理的時候 可能會用到這個屬性 https://stackoverflow.com/questions/45463757/what-is-interface-based-proxying
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
//這裡建立了一個新的 ProxyFactory
ProxyFactory proxyFactory = new ProxyFactory();
//copy原類的配置 重寫賦值的動作 單例變多例
proxyFactory.copyFrom(this);
//這裡是 判斷是否強制使用 cglib
if (!proxyFactory.isProxyTargetClass()) {
//這裡 判斷是 使用jdk動態代理 還是cglib代理
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
//這裡又重寫構建了一次 Advisor 看看是否 設定了通用的攔截
//這裡講所有的Advisor和配置的通用攔截都轉換為了Advisor型別
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
for (Advisor advisor : advisors) {
proxyFactory.addAdvisor(advisor);
}
//targetSource 裡是包含目標物件的
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
//建立代理物件 關於建立代理物件的分析 請參考:https://blog.csdn.net/zknxx/article/details/79764107
return proxyFactory.getProxy(getProxyClassLoader());
}