上篇Spring AOP學(xué)習(xí)中已經(jīng)基本介紹了AOP是如何使用的,本文章來(lái)說(shuō)說(shuō)AOP注解方法的源碼細(xì)節(jié)
先提幾個(gè)問(wèn)題,在接下來(lái)的源碼學(xué)習(xí)中發(fā)現(xiàn)答案
-
<aop:aspectj-autoproxy />
的工作原理是什么搬卒,能帶來(lái)什么作用 - @Aspect是在什么時(shí)候被操作的
- 各個(gè)切入點(diǎn)是按照什么樣的順序執(zhí)行
- 切入點(diǎn)是如何和對(duì)應(yīng)的bean綁定在一起的
具體的demo可以看Spring AOP學(xué)習(xí)#注解
XML配置解析
AOP的配置最簡(jiǎn)單的方法就是在xml中加入<aop:aspectj-autoproxy />
瑟俭,應(yīng)該很清楚spring是選擇什么命名空間去解析了,直接定位到AopNamespaceHandler 類契邀,而且定位的是AspectJAutoProxyBeanDefinitionParser解析器摆寄,如果這點(diǎn)有什么疑問(wèn)的話,最好是再看看spring xml的bean提取 源碼學(xué)習(xí),看完就懂了為什么會(huì)直接定位到該解析器
public class AopNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
// In 2.0 XSD as well as in 2.1 XSD.
registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
// AspectJAutoProxyBeanDefinitionParser 是我們這次關(guān)注的類
registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}
}
AspectJAutoProxyBeanDefinitionParser 類
class AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser {
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
// 可以生成AnnotationAwareAspectJAutoProxyCreator類的beandefinition
// 并注冊(cè)到IOC容器中
extendBeanDefinition(element, parserContext);
// 擴(kuò)展該bean的屬性信息
return null;
}
private void extendBeanDefinition(Element element, ParserContext parserContext) {
BeanDefinition beanDef =
parserContext.getRegistry().getBeanDefinition(AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME);
// 該bean其實(shí)就是上面所說(shuō)的AnnotationAwareAspectJAutoProxyCreator的beandefinition
if (element.hasChildNodes()) {
addIncludePatterns(element, parserContext, beanDef);
// 如果包含了子節(jié)點(diǎn)可以添加額外的includePattern
}
}
private void addIncludePatterns(Element element, ParserContext parserContext, BeanDefinition beanDef) {
ManagedList<TypedStringValue> includePatterns = new ManagedList<TypedStringValue>();
NodeList childNodes = element.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
Node node = childNodes.item(i);
if (node instanceof Element) {
Element includeElement = (Element) node;
TypedStringValue valueHolder = new TypedStringValue(includeElement.getAttribute("name"));
// 獲取子屬性key為name的值
valueHolder.setSource(parserContext.extractSource(includeElement));
includePatterns.add(valueHolder);
}
}
if (!includePatterns.isEmpty()) {
includePatterns.setSource(parserContext.extractSource(element));
beanDef.getPropertyValues().add("includePatterns", includePatterns);
// 給該beandefinition賦屬性值坯门,includePatterns
}
}
}
如上述代碼中的AnnotationAwareAspectJAutoProxyCreator類創(chuàng)建中微饥,如果跳進(jìn)去能夠看到還可以為該類設(shè)置proxy-target-class
和expose-proxy
兩個(gè)boolean屬性值。
也可以設(shè)置子屬性值name,例如下面的設(shè)置
<aop:aspectj-autoproxy proxy-target-class="false" expose-proxy="true">
<aop:include name="******" />
</aop:aspectj-autoproxy>
這樣就清楚了這個(gè)xml配置的原理是如何田盈,其實(shí)就是新添加了一個(gè)beandefinition而已畜号。
Aspect 掃描和實(shí)例化
spring正常的注冊(cè)的bean缴阎,如果沒(méi)有加@Aspect注解也是沒(méi)有用的允瞧,那么就來(lái)學(xué)習(xí)下是在什么時(shí)候被掃描到,以及后續(xù)的操作是什么蛮拔。
如果大概看了AnnotationAwareAspectJAutoProxyCreator類的相關(guān)內(nèi)容述暂,可以知道AOP所有的aspect以及pointCut都存儲(chǔ)在該對(duì)象中,所以掃描所有的注解@Aspect類建炫,肯定是在AnnotationAwareAspectJAutoProxyCreator類的實(shí)例化之后畦韭!
在refresh()代碼中,在實(shí)例化具體的bean之前肛跌,已經(jīng)完成了spring層面的bean實(shí)例
在接下來(lái)對(duì)org.springframework.context.event.internalEventListenerProcessor對(duì)象實(shí)例化的過(guò)程中會(huì)完成對(duì)@aspect類的掃描操作艺配,并把相關(guān)信息注入到上圖圈住的AnnotationAwareAspectJAutoProxyCreator類中。
隨著代碼調(diào)試到AbstractAutoProxyCreator文件
AbstractAutoProxyCreator 類
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
Object cacheKey = getCacheKey(beanClass, beanName);
// 從當(dāng)前的cache容器獲取到bean的name
if (beanName == null || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
// 該advisedBeans已經(jīng)包含了該key衍慎,則直接退出不考慮
}
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
// 該bean不符合所有獲取到的切面转唉,設(shè)置為false
// shouldSkip方法看下面的代碼
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
// 所有的注解信息已經(jīng)獲取到了
// 具體通過(guò)代理類生成一個(gè)對(duì)象信息
if (beanName != null) {
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
this.targetSourcedBeans.add(beanName);
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
// 利用ProxyFactory 生成一個(gè)新的對(duì)象
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
}
return null;
}
AspectJAwareAdvisorAutoProxyCreator 類
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 獲取所有的advisor,也就是PointCut稳捆,具體細(xì)節(jié)可看下面的函數(shù)執(zhí)行過(guò)程代碼
for (Advisor advisor : candidateAdvisors) {
if (advisor instanceof AspectJPointcutAdvisor) {
if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) {
return true;
}
}
}
return super.shouldSkip(beanClass, beanName);
}
BeanFactoryAdvisorRetrievalHelper 類
這個(gè)類是AnnotationAwareAspectJAutoProxyCreator的一個(gè)對(duì)象
public List<Advisor> findAdvisorBeans() {
String[] advisorNames = null;
synchronized (this) {
advisorNames = this.cachedAdvisorBeanNames;
if (advisorNames == null) {
// 還沒(méi)準(zhǔn)備好赠法,首次進(jìn)入該函數(shù)時(shí),為null
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
// 獲取到IOC容器中乔夯,所有類的類型是Advisor.class的
// 當(dāng)然就我們當(dāng)前的demo而言肯定是沒(méi)有的砖织,只有加上了Advisor.class注解的類
// 會(huì)繼續(xù)進(jìn)入到**buildAspectJAdvisors函數(shù)**中去獲取到注解為Advisor.class的類
this.cachedAdvisorBeanNames = advisorNames;
}
}
if (advisorNames.length == 0) {
return new LinkedList<Advisor>();
}
List<Advisor> advisors = new LinkedList<Advisor>();
for (String name : advisorNames) {
if (isEligibleBean(name)) {
if (this.beanFactory.isCurrentlyInCreation(name)) {
if (logger.isDebugEnabled()) {
logger.debug("Skipping currently created advisor '" + name + "'");
}
}
else {
try {
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;
}
public List<Advisor> buildAspectJAdvisors() {
List<String> aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
// 第一次進(jìn)入款侵,確實(shí)為null
synchronized (this) {
aspectNames = this.aspectBeanNames;
// spring中為了確保線程安全,存在大量的類似double-check的代碼
if (aspectNames == null) {
List<Advisor> advisors = new LinkedList<Advisor>();
aspectNames = new LinkedList<String>();
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
// 獲取IOC所有類型為Object的類名稱(肯定包含了注解@Aspect的相關(guān)類)
for (String beanName : beanNames) {
if (!isEligibleBean(beanName)) {
// 類名和includePatterns正則匹配不通過(guò)侧纯,則跳過(guò)新锈,起到一個(gè)過(guò)濾的作用
// 匹配的是類似于com.demo.*這樣的類名稱
// 和上面說(shuō)的<aop:include name="******" />相關(guān)聯(lián)
continue;
}
Class<?> beanType = this.beanFactory.getType(beanName);
if (beanType == null) {
// 獲取其類型,如果為null眶熬,無(wú)效壕鹉,跳過(guò)
continue;
}
if (this.advisorFactory.isAspect(beanType)) {
// 注解包含了@Aspect 并且沒(méi)有被AspectJ編譯(字段以ajc$開(kāi)頭)的類
aspectNames.add(beanName);
// 本demo的beanName就是animalAop
AspectMetadata amd = new AspectMetadata(beanType, beanName);
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
// 獲取該類所有的方法烈炭,例如@Before抬闯、@After等
// 取到該類所有的方法,按照Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class 的順序排序
// 依次遍歷榜田,如果發(fā)現(xiàn)了上述的注解牍白,則保存pointCut到一個(gè)容器中
// 獲取該類所有的共有方法脊凰,如果符合要求,也保存到容器中茂腥,最后返回到List中
if (this.beanFactory.isSingleton(beanName)) {
this.advisorsCache.put(beanName, classAdvisors);
// 如果是單例狸涌,則保存到cache共,否則保存到工廠cache中
}
else {
this.aspectFactoryCache.put(beanName, factory);
}
advisors.addAll(classAdvisors);
}
else {
// Per target or per this.
if (this.beanFactory.isSingleton(beanName)) {
throw new IllegalArgumentException("Bean with name '" + beanName +
"' is a singleton, but aspect instantiation model is not singleton");
}
MetadataAwareAspectInstanceFactory factory =
new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
this.aspectFactoryCache.put(beanName, factory);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
}
// 這里給aspectNames 賦值
// 需要注意到一旦賦值了最岗,就不會(huì)為空帕胆,則不會(huì)再去掃描所有的bean,得到全部的AOP信息
this.aspectBeanNames = aspectNames;
return advisors;
}
}
}
// 能運(yùn)行到這里的肯定是第二次執(zhí)行般渡,獲取到需要的AOP的pointCut信息
if (aspectNames.isEmpty()) {
return Collections.emptyList();
}
List<Advisor> advisors = new LinkedList<Advisor>();
for (String aspectName : aspectNames) {
List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
if (cachedAdvisors != null) {
advisors.addAll(cachedAdvisors);
}
else {
MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
return advisors;
}
最后實(shí)例化代理對(duì)象AnimalImpl對(duì)象懒豹,經(jīng)過(guò)調(diào)試來(lái)到了
AbstractAutoProxyCreator 文件
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;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
// 得到相關(guān)的advice
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
// 這一步就是最關(guān)鍵的步驟,最后生成代理類
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
如下圖驯用,調(diào)試中生成了最終的代理類
至此脸秽,整個(gè)的代理類的實(shí)現(xiàn)過(guò)程就全部完成了。
總結(jié)下整個(gè)AOP注解操作的過(guò)程
1蝴乔、先利用xml配置记餐,添加AnnotationAwareAspectJAutoProxyCreator類到IOC容器中
2、在實(shí)例化各種beanpostprocessor的時(shí)候薇正,掃描IOC所有的bean片酝,如果配置了includePattern屬性,還需要對(duì)IOC容器的所有bean進(jìn)行正則匹配挖腰,通過(guò)的才會(huì)進(jìn)行接下來(lái)的操作
3雕沿、所有合適的bean遍歷找到注解為@Aspect的類,輪詢bean的方法曙聂,如果包含了Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class
的注解方法晦炊,也需要收集起來(lái),最后形成kv對(duì),添加到AnnotationAwareAspectJAutoProxyCreator的cache容器中
4断国、實(shí)例化被代理的類之前需要實(shí)例化本身
5贤姆、從AnnotationAwareAspectJAutoProxyCreator存儲(chǔ)的所有advisor匹配出符合規(guī)則的advisor
具體可看AopUtils抽象類的findAdvisorsThatCanApply 方法
6、最后生成一個(gè)ProxyFactory稳衬,添加上述得到的各種數(shù)據(jù)霞捡,生成代理類
再來(lái)回答文章前提到的幾個(gè)問(wèn)題
-
<aop:aspectj-autoproxy />
的工作原理是什么,能帶來(lái)什么作用
無(wú)需再?gòu)?qiáng)調(diào)薄疚,如果還是無(wú)法理解碧信,可以仔細(xì)閱讀spring xml的bean提取 源碼學(xué)習(xí),帶來(lái)的作用就是新增了一個(gè)管理Aspect的類,所有的advisor都是存放在這個(gè)類中
- @Aspect是在什么時(shí)候被操作的
beanpostprocessor實(shí)例化的時(shí)候街夭,特指
org.springframework.context.event.internalEventListenerProcessor
類的實(shí)例化時(shí)砰碴,會(huì)去掃描所有的bean,檢查是否存在@Aspect注解板丽,如果有該注解呈枉,則添加到AnnotationAwareAspectJAutoProxyCreator中
- 各個(gè)切入點(diǎn)是按照什么樣的順序執(zhí)行
切入點(diǎn)是按照
Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class
自定義的排序規(guī)則sort的操作的
- 切入點(diǎn)是如何和對(duì)應(yīng)的bean綁定在一起的
相互獨(dú)立的,只有在bean具體生成的時(shí)候從AnnotationAwareAspectJAutoProxyCreator中獲取到合適的切面以及切點(diǎn)信息埃碱,最后生成代理類猖辫。