上兩篇文章已經(jīng)介紹了AOP的使用方法以及AOP注解原理相恃,如果有疑問,可以看看Spring AOP學習 和 Spring AOP 注解配置 源碼學習 非区。
現(xiàn)在來學習XML配置的操作原理告喊。
XML配置解析
根據(jù)<aop:config>
直接定位到其命名空間的解析器ConfigBeanDefinitionParser
public BeanDefinition parse(Element element, ParserContext parserContext) {
CompositeComponentDefinition compositeDef =
new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
parserContext.pushContainingComponent(compositeDef);
configureAutoProxyCreator(parserContext, element);
// 直接創(chuàng)建了一個代理對象,AspectJAwareAdvisorAutoProxyCreator類
// 這個類和注解實現(xiàn)的類不一樣星著!
List<Element> childElts = DomUtils.getChildElements(element);
// 掃描葉子節(jié)點的信息,包含了pointCut粗悯、adivsor虚循、aspect等信息
for (Element elt: childElts) {
String localName = parserContext.getDelegate().getLocalName(elt);
if (POINTCUT.equals(localName)) {
parsePointcut(elt, parserContext);
}
else if (ADVISOR.equals(localName)) {
parseAdvisor(elt, parserContext);
}
else if (ASPECT.equals(localName)) {
parseAspect(elt, parserContext);
}
}
parserContext.popAndRegisterContainingComponent();
return null;
}
如上圖就是在xml文件解析完成之后在IOC的map中保存的數(shù)據(jù),其中pc
這個pointCut被當做一個新的beandefinition插入到map中样傍,此外所有的advisor也被插入到map中横缔。
接下來就需要進行實例化beandefinition操作,在beanFactory.preInstantiateSingletons()
操作會依次遍歷所有已經(jīng)存儲好的beandefinition列表衫哥。如下圖
在Spring AOP 注解配置 源碼學習 中有說過在實例化org.springframework.context.event.internalEventListenerProcessor時才會進行AOP操作茎刚,原因是什么呢,很簡單撤逢,因為列表的前面幾個beandefinition也是postbeanprocessor膛锭,已經(jīng)在invokebeanpostprocessor的時候進行實例化了,所有也就輪流到了internalEventListenerProcessor的實例化而已蚊荣。
AbstractAutowireCapableBeanFactory 類
try {
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
需要注意到AspectJAwareAdvisorAutoProxyCreator
這個需要實例化的bean是beanPostProcessors類也是InstantiationAwareBeanPostProcessor類初狰。所有會進入到上面的resolveBeforeInstantiation方法
如上述代碼會遍歷所有的Advisor類,并實例化互例。
實例化操作
在對People類的實例化操作時奢入,肯定會獲取到上述已經(jīng)實例化好的advisor,并利用cglib或者動態(tài)代理的方式生成具體對象敲霍。
AbstractAutowireCapableBeanFactory 類
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
// 重點關(guān)注AspectJAwareAdvisorAutoProxyCreator對象的方法
// 會調(diào)用 AbstractAutoProxyCreator 類的方法
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
AbstractAutoProxyCreator 類
// 這里的bean已經(jīng)完成了實例化
// 例如本demo的People對象俊马,已經(jīng)完成了實例化,然后添加代理proxy操作
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
// 還沒有處理的bean肩杈,調(diào)用wrapIfNecessary
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
// 需要進行proxy的包裝處理
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
// 已經(jīng)處理過了柴我,直接返回
// 這個this就是AspectJAwareAdvisorAutoProxyCreator 對象
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
// 這個false表示了沒有合適的advisor需要被包裝處理
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
// isInfrastructureClass 是檢測類是否屬于Advice、Pointcut扩然、Advisor艘儒、AopInfrastructureBean 類中的一種 如果是則不應(yīng)該被處理
// skip函數(shù)在上一篇已經(jīng)介紹過了,就是確認是否存在合適的advisor對象
// skip返回true表示了沒有合適的advisor需要被處理,則當前該bean沒有合適的proxy
// 設(shè)置adviseBean為false界睁,并且直接返回
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
// 很關(guān)鍵的一個操作觉增,找出合適的advisor對象
// 并且其中就有規(guī)則的判斷邏輯,等下再細細介紹【1翻斟、匹配execution邏輯規(guī)則】
if (specificInterceptors != DO_NOT_PROXY) {
// 存在合適的advisor對象信息
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 設(shè)置為true逾礁,免得下次再計算
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
// 創(chuàng)建包裝的對象信息,并返回访惜,其中就有是使用動態(tài)代理還是cglib產(chǎn)生對象的判斷存在【2嘹履、代理對象生成原理】
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
// 否則,設(shè)置其值為false债热,返回返回
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
1砾嫉、【匹配execution邏輯規(guī)則】
AbstractAdvisorAutoProxyCreator 類
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
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();
// 所有合適的advisor對象列表
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
// 找出所有可以使用的advisor
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
// 這個sort操作 注解方式和XML配置方式是一致的
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
AopUtils 類
如下截圖,運行到該代碼的參數(shù)細節(jié)
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
// 列表為空窒篱,直接返回
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new LinkedList<Advisor>();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
// 是IntroductionAdvisor 類而且 通過expression 的規(guī)則校驗
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor) {
// 已經(jīng)處理了不再處理
continue;
}
if (canApply(candidate, clazz, hasIntroductions)) {
// 這里的canApply和上面就差距一個hasIntroductions的參數(shù)
// 如果包含了advisor對象且通過校驗位true參數(shù)
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
if (advisor instanceof IntroductionAdvisor) {
// 可看出hasIntroductions只對PointCut才有用焕刮,所以才有了上面的多次canApply操作
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
else if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pca = (PointcutAdvisor) advisor;
// 又是被封裝了一層的canApply方法
// 通過getPointCut方法獲取具體的pointCut信息
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
// 沒有pointCut,假定為可以應(yīng)用墙杯,返回true
return true;
}
}
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
// 對類名稱進行一個基礎(chǔ)的(maybe)的判斷操作配并,如果返回false,則認為不可用高镐,返回false
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
MethodMatcher methodMatcher = pc.getMethodMatcher();
if (methodMatcher == MethodMatcher.TRUE) {
// 該方法正好匹配為true荐绝,則直接返回true
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) {
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
// 獲取該類所有的方法形成一個列表,進行遍歷匹配操作
// 看到這個函數(shù)已經(jīng)就很清楚了避消,簡而言之就是通過函數(shù)名稱進行匹配操作
for (Method method : methods) {
if ((introductionAwareMethodMatcher != null &&
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
expression="execution(* com.demo.Aop..(..))" 在execution中的參數(shù)就是函數(shù)的匹配
第一個* 表示為 private、public
com.demo.Aop.* 表示為 Aop文件夾下面所有的class文件
第二個* 表示為 類文件下的具體函數(shù)名稱
(..) 表示為 參數(shù)的情況
如上圖中所示召夹,原本存在6個advisor岩喷,經(jīng)過canApply操作,只剩下了5個监憎,其中的* com.demo.Aop1.*
就被過濾掉了纱意。
所有匹配execution的邏輯規(guī)則是先對類名稱進行基礎(chǔ)的判斷,然后獲取被匹配的類名稱的所有函數(shù)精準匹配
sort操作
此外在findEligibleAdvisors函數(shù)中的sort操作前后對比
2鲸阔、【代理對象生成原理】
在wrapIfNecessary
方法中獲取到合適的advisor列表之后偷霉,肯定需要需要ProxyFactory根據(jù)advisor列表信息等產(chǎn)生具體對象
AbstractAutoProxyCreator 類
protected Object createProxy(
Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
// 給當前的類加上屬性O(shè)RIGINAL_TARGET_CLASS_ATTRIBUTE
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
ProxyFactory proxyFactory = new ProxyFactory();
// spring所有的套路都是這樣的,大量利用工廠模式產(chǎn)生具體對象
proxyFactory.copyFrom(this);
// 拷貝了當前的數(shù)據(jù)到當前的工廠中
if (!proxyFactory.isProxyTargetClass()) {
// 如果該bean存在PRESERVE_TARGET_CLASS_ATTRIBUTE屬性褐筛,設(shè)置ProxyTargetClass為true
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
// 檢查是否存在接口类少,能否正常使用
// 不過有毒的是,在發(fā)現(xiàn)沒有合適的接口時渔扎,又設(shè)置ProxyTargetClass為true
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
// 再包裝一層advisor
for (Advisor advisor : advisors) {
proxyFactory.addAdvisor(advisor);
}
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
// spring依舊的套路很多custom方法都是接口
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// 真正創(chuàng)建對象的步驟
return proxyFactory.getProxy(getProxyClassLoader());
}
DefaultAopProxyFactory 類
ProxyFactory包含的默認的代理工廠DefaultAopProxyFactory
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
// 沒有設(shè)置目標targetClass,拋出異常
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)) {
// 如果是繼承自接口或者ProxyClass值為true(為代理類)
// 則使用java的動態(tài)代理產(chǎn)生對象
return new JdkDynamicAopProxy(config);
}
// 沒有繼承自接口而且不是proxy類
// 則使用cglib 產(chǎn)生對象
// 這里有點需要注意到的是 cglib 同樣可以使用接口實現(xiàn)對象硫狞,只是在spring中如此設(shè)置而已
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
現(xiàn)在就介紹了spring中AOP的代理對象實現(xiàn)細節(jié),同時使用其他工廠產(chǎn)生對象也是采用同樣的模式。
現(xiàn)在整個的XML配置的學習就結(jié)束了残吩,后續(xù)還會再總結(jié)一下xml配置和注解方式的差異和一些未曾注意到的細節(jié)财忽,具體梳理其中的細節(jié)信息。