码迷,mamicode.com
首页 > 编程语言 > 详细

spring aop(四)

时间:2017-08-07 00:21:12      阅读:188      评论:0      收藏:0      [点我收藏+]

标签:join   record   oop   ext   manual   post   require   bean   cache   

 

直接找到解析aop标签的方法:

 

 1 protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
 2         if (delegate.isDefaultNamespace(root)) {
 3             NodeList nl = root.getChildNodes();
 4             for (int i = 0; i < nl.getLength(); i++) {
 5                 Node node = nl.item(i);
 6                 if (node instanceof Element) {
 7                     Element ele = (Element) node;
 8                     if (delegate.isDefaultNamespace(ele)) {
 9                         parseDefaultElement(ele, delegate);
10                     }
11                     else {
12                         delegate.parseCustomElement(ele);
13                     }
14                 }
15             }
16         }
17         else {
18             delegate.parseCustomElement(root);
19         }
20     }

 

由于aop属于自定义标签,所以它会执行第12行的代码。

1 public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
2         String namespaceUri = getNamespaceURI(ele);
3         NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
4         if (handler == null) {
5             error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
6             return null;
7         }
8         return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
9     }

通过aop标签获取到它的命名空间uri,通过命名空间去找到对应的命名空间处理器,这个处理器的定义在springaop包下的一个叫spring.handlers的文件里声明了,它的内容是这样的

 

http\://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler

 

spring就是通过这个声明去加载这个aop命名空间处理器,通过反射的方式构建对象。构建好对象后调用它的parse方法

 

 1 public BeanDefinition parse(Element element, ParserContext parserContext) {
 2         CompositeComponentDefinition compositeDef =
 3                 new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
 4         parserContext.pushContainingComponent(compositeDef);
 5 
 6         configureAutoProxyCreator(parserContext, element);
 7 
 8         List<Element> childElts = DomUtils.getChildElements(element);
 9         for (Element elt: childElts) {
10             String localName = parserContext.getDelegate().getLocalName(elt);
11             if (POINTCUT.equals(localName)) {
12                 parsePointcut(elt, parserContext);
13             }
14             else if (ADVISOR.equals(localName)) {
15                 parseAdvisor(elt, parserContext);
16             }
17             else if (ASPECT.equals(localName)) {
18                 parseAspect(elt, parserContext);
19             }
20         }
21 
22         parserContext.popAndRegisterContainingComponent();
23         return null;
24     }

 

第6行的代码配置了一个org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator类,像前面的bean一样被定义成了一个BeanDefinition对象保存到了BeanFactory的beanDefinitionMap中。这个AspectJAwareAdvisorAutoProxyCreator是用来干什么的呢?看到后面才知道。

第8行获取到了这个aop:config下的子元素

是pointcut标签就处理pointcut,是advisor就处理advisor

看到第18行我们配置了一个切面,所以spring会解析这个aspect标签

 1 private void parseAspect(Element aspectElement, ParserContext parserContext) {
 2         String aspectId = aspectElement.getAttribute(ID);
 3         String aspectName = aspectElement.getAttribute(REF);
 4 
 5         try {
 6             this.parseState.push(new AspectEntry(aspectId, aspectName));
 7             List<BeanDefinition> beanDefinitions = new ArrayList<BeanDefinition>();
 8             List<BeanReference> beanReferences = new ArrayList<BeanReference>();
 9 
10             List<Element> declareParents = DomUtils.getChildElementsByTagName(aspectElement, DECLARE_PARENTS);
11             for (int i = METHOD_INDEX; i < declareParents.size(); i++) {
12                 Element declareParentsElement = declareParents.get(i);
13                 beanDefinitions.add(parseDeclareParents(declareParentsElement, parserContext));
14             }
15 
16             // We have to parse "advice" and all the advice kinds in one loop, to get the
17             // ordering semantics right.
18             NodeList nodeList = aspectElement.getChildNodes();
19             boolean adviceFoundAlready = false;
20             for (int i = 0; i < nodeList.getLength(); i++) {
21                 Node node = nodeList.item(i);
22                 if (isAdviceNode(node, parserContext)) {
23                     if (!adviceFoundAlready) {
24                         adviceFoundAlready = true;
25                         if (!StringUtils.hasText(aspectName)) {
26                             parserContext.getReaderContext().error(
27                                     "<aspect> tag needs aspect bean reference via ‘ref‘ attribute when declaring advices.",
28                                     aspectElement, this.parseState.snapshot());
29                             return;
30                         }
31                         beanReferences.add(new RuntimeBeanReference(aspectName));
32                     }
33                     AbstractBeanDefinition advisorDefinition = parseAdvice(
34                             aspectName, i, aspectElement, (Element) node, parserContext, beanDefinitions, beanReferences);
35                     beanDefinitions.add(advisorDefinition);
36                 }
37             }
38 
39             AspectComponentDefinition aspectComponentDefinition = createAspectComponentDefinition(
40                     aspectElement, aspectId, beanDefinitions, beanReferences, parserContext);
41             parserContext.pushContainingComponent(aspectComponentDefinition);
42 
43             List<Element> pointcuts = DomUtils.getChildElementsByTagName(aspectElement, POINTCUT);
44             for (Element pointcutElement : pointcuts) {
45                 parsePointcut(pointcutElement, parserContext);
46             }
47 
48             parserContext.popAndRegisterContainingComponent();
49         }
50         finally {
51             this.parseState.pop();
52         }
53     }

第22行表示解析在aspect标签下的通知,假如此时读取到了一个before标签,开始解析这个通知

 1 private AbstractBeanDefinition parseAdvice(
 2             String aspectName, int order, Element aspectElement, Element adviceElement, ParserContext parserContext,
 3             List<BeanDefinition> beanDefinitions, List<BeanReference> beanReferences) {
 4 
 5         try {
 6             this.parseState.push(new AdviceEntry(parserContext.getDelegate().getLocalName(adviceElement)));
 7 
 8             // create the method factory bean
 9             RootBeanDefinition methodDefinition = new RootBeanDefinition(MethodLocatingFactoryBean.class);
10             methodDefinition.getPropertyValues().add("targetBeanName", aspectName);
11             methodDefinition.getPropertyValues().add("methodName", adviceElement.getAttribute("method"));
12             methodDefinition.setSynthetic(true);
13 
14             // create instance factory definition
15             RootBeanDefinition aspectFactoryDef =
16                     new RootBeanDefinition(SimpleBeanFactoryAwareAspectInstanceFactory.class);
17             aspectFactoryDef.getPropertyValues().add("aspectBeanName", aspectName);
18             aspectFactoryDef.setSynthetic(true);
19 
20             // register the pointcut
21             AbstractBeanDefinition adviceDef = createAdviceDefinition(
22                     adviceElement, parserContext, aspectName, order, methodDefinition, aspectFactoryDef,
23                     beanDefinitions, beanReferences);
24 
25             // configure the advisor
26             RootBeanDefinition advisorDefinition = new RootBeanDefinition(AspectJPointcutAdvisor.class);
27             advisorDefinition.setSource(parserContext.extractSource(adviceElement));
28             advisorDefinition.getConstructorArgumentValues().addGenericArgumentValue(adviceDef);
29             if (aspectElement.hasAttribute(ORDER_PROPERTY)) {
30                 advisorDefinition.getPropertyValues().add(
31                         ORDER_PROPERTY, aspectElement.getAttribute(ORDER_PROPERTY));
32             }
33 
34             // register the final advisor
35             parserContext.getReaderContext().registerWithGeneratedName(advisorDefinition);
36 
37             return advisorDefinition;
38         }
39         finally {
40             this.parseState.pop();
41         }
42     }

第九行创建了一个方法工厂bean,MethodLocatingFactoryBean这个类有targetBeanName,methodName,method三个属性,method是methodName的对应Method对象。

第10行给methodDefinition设置属性targetBeanName为切面类的beanName,也就是id

第11行给methodDefinition设置属性methodName,表示这个通知要切入的方法名。

 

比如:

1 <aop:config>
2         <aop:aspect id="aspect" ref="aspectID">
3             <aop:pointcut expression="execution(* com.test.*.*(..))"
4                 id="cutpoint" />
5             <aop:before method="before" pointcut-ref="cutpoint" />
6             
7         </aop:aspect>
8 
9     </aop:config>

那么targetBeanName为aspectID,methodName为before。

第16行创建了一个实例工厂bean,SimpleBeanFactoryAwareAspectInstanceFactory这个类除了父类的具有两个属性aspectBeanName,beanFactory,aspectBeanName指的切面的beanName,也就是上面的aspectID,beanFactory指的BeanFactory的实例

第17行给这个SimpleBeanFactoryAwareAspectInstanceFactory定义属性,aspectBeanName为aspectID

进入第21行

 1 private AbstractBeanDefinition createAdviceDefinition(
 2             Element adviceElement, ParserContext parserContext, String aspectName, int order,
 3             RootBeanDefinition methodDef, RootBeanDefinition aspectFactoryDef,
 4             List<BeanDefinition> beanDefinitions, List<BeanReference> beanReferences) {
 5 
 6         RootBeanDefinition adviceDefinition = new RootBeanDefinition(getAdviceClass(adviceElement, parserContext));
 7         adviceDefinition.setSource(parserContext.extractSource(adviceElement));
 8 
 9         adviceDefinition.getPropertyValues().add(ASPECT_NAME_PROPERTY, aspectName);
10         adviceDefinition.getPropertyValues().add(DECLARATION_ORDER_PROPERTY, order);
11 
12         if (adviceElement.hasAttribute(RETURNING)) {
13             adviceDefinition.getPropertyValues().add(
14                     RETURNING_PROPERTY, adviceElement.getAttribute(RETURNING));
15         }
16         if (adviceElement.hasAttribute(THROWING)) {
17             adviceDefinition.getPropertyValues().add(
18                     THROWING_PROPERTY, adviceElement.getAttribute(THROWING));
19         }
20         if (adviceElement.hasAttribute(ARG_NAMES)) {
21             adviceDefinition.getPropertyValues().add(
22                     ARG_NAMES_PROPERTY, adviceElement.getAttribute(ARG_NAMES));
23         }
24 
25         ConstructorArgumentValues cav = adviceDefinition.getConstructorArgumentValues();
26         cav.addIndexedArgumentValue(METHOD_INDEX, methodDef);
27 
28         Object pointcut = parsePointcutProperty(adviceElement, parserContext);
29         if (pointcut instanceof BeanDefinition) {
30             cav.addIndexedArgumentValue(POINTCUT_INDEX, pointcut);
31             beanDefinitions.add((BeanDefinition) pointcut);
32         }
33         else if (pointcut instanceof String) {
34             RuntimeBeanReference pointcutRef = new RuntimeBeanReference((String) pointcut);
35             cav.addIndexedArgumentValue(POINTCUT_INDEX, pointcutRef);
36             beanReferences.add(pointcutRef);
37         }
38 
39         cav.addIndexedArgumentValue(ASPECT_INSTANCE_FACTORY_INDEX, aspectFactoryDef);
40 
41         return adviceDefinition;
42     }

第6行创建了一个关于advice的BeanDefinition。首先它调用了getAdviceClass方法,我们进去看看

 1 private Class<?> getAdviceClass(Element adviceElement, ParserContext parserContext) {
 2         String elementName = parserContext.getDelegate().getLocalName(adviceElement);
 3         if (BEFORE.equals(elementName)) {
 4             return AspectJMethodBeforeAdvice.class;
 5         }
 6         else if (AFTER.equals(elementName)) {
 7             return AspectJAfterAdvice.class;
 8         }
 9         else if (AFTER_RETURNING_ELEMENT.equals(elementName)) {
10             return AspectJAfterReturningAdvice.class;
11         }
12         else if (AFTER_THROWING_ELEMENT.equals(elementName)) {
13             return AspectJAfterThrowingAdvice.class;
14         }
15         else if (AROUND.equals(elementName)) {
16             return AspectJAroundAdvice.class;
17         }
18         else {
19             throw new IllegalArgumentException("Unknown advice kind [" + elementName + "].");
20         }
21     }

看见了吗?根据通知的类型返回相应的通知类,before对应AspectJMethodBeforeAdvice类,after对应AspectJAfterAdvice类,before和after对应的通知类的内部结构有些区别,before对应的类有before方法,但after对应的通知类是没有after方法的,代替使用的是一个invoke方法。现在不深入探讨它们是干什么的,到了调用通知方法的时候自然就明白了,这里先不管。

我们再次回到createAdviceDefinition方法

 1 private AbstractBeanDefinition createAdviceDefinition(
 2             Element adviceElement, ParserContext parserContext, String aspectName, int order,
 3             RootBeanDefinition methodDef, RootBeanDefinition aspectFactoryDef,
 4             List<BeanDefinition> beanDefinitions, List<BeanReference> beanReferences) {
 5 
 6         RootBeanDefinition adviceDefinition = new RootBeanDefinition(getAdviceClass(adviceElement, parserContext));
 7         adviceDefinition.setSource(parserContext.extractSource(adviceElement));
 8 
 9         adviceDefinition.getPropertyValues().add(ASPECT_NAME_PROPERTY, aspectName);
10         adviceDefinition.getPropertyValues().add(DECLARATION_ORDER_PROPERTY, order);
11 
12         if (adviceElement.hasAttribute(RETURNING)) {
13             adviceDefinition.getPropertyValues().add(
14                     RETURNING_PROPERTY, adviceElement.getAttribute(RETURNING));
15         }
16         if (adviceElement.hasAttribute(THROWING)) {
17             adviceDefinition.getPropertyValues().add(
18                     THROWING_PROPERTY, adviceElement.getAttribute(THROWING));
19         }
20         if (adviceElement.hasAttribute(ARG_NAMES)) {
21             adviceDefinition.getPropertyValues().add(
22                     ARG_NAMES_PROPERTY, adviceElement.getAttribute(ARG_NAMES));
23         }
24 
25         ConstructorArgumentValues cav = adviceDefinition.getConstructorArgumentValues();
26         cav.addIndexedArgumentValue(METHOD_INDEX, methodDef);
27 
28         Object pointcut = parsePointcutProperty(adviceElement, parserContext);
29         if (pointcut instanceof BeanDefinition) {
30             cav.addIndexedArgumentValue(POINTCUT_INDEX, pointcut);
31             beanDefinitions.add((BeanDefinition) pointcut);
32         }
33         else if (pointcut instanceof String) {
34             RuntimeBeanReference pointcutRef = new RuntimeBeanReference((String) pointcut);
35             cav.addIndexedArgumentValue(POINTCUT_INDEX, pointcutRef);
36             beanReferences.add(pointcutRef);
37         }
38 
39         cav.addIndexedArgumentValue(ASPECT_INSTANCE_FACTORY_INDEX, aspectFactoryDef);
40 
41         return adviceDefinition;
42     }

创建了adviceDefinition后第9第10行分别定义了通知类的一些属性,aspectName,declarationOrder

12 16 20行是判断有没有定义returning throwing arg-names属性,如果配置了,那么要给通知类加上

第25 26行要给这个通知类定义构造参数,通知类中的需要以下构造参数,比如AspectJMethodBeforeAdvice类的构造参数

AspectJMethodBeforeAdvice(
Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif)

它需要一个method对象,切面表达式连接点,切面实例工厂

第25 26行给这个通知的BeanDefinition的构造加入了第一个参数的BeanDefinition==》前面已经创建好的包装MethodLocatingFactoryBean的methodDefinition。

第28行是去通知标签(如before标签)上去得pointcut或者是pointcut-ref,代码如下:

 1 private Object parsePointcutProperty(Element element, ParserContext parserContext) {
 2         if (element.hasAttribute(POINTCUT) && element.hasAttribute(POINTCUT_REF)) {
 3             parserContext.getReaderContext().error(
 4                     "Cannot define both ‘pointcut‘ and ‘pointcut-ref‘ on <advisor> tag.",
 5                     element, this.parseState.snapshot());
 6             return null;
 7         }
 8         else if (element.hasAttribute(POINTCUT)) {
 9             // Create a pointcut for the anonymous pc and register it.
10             String expression = element.getAttribute(POINTCUT);
11             AbstractBeanDefinition pointcutDefinition = createPointcutDefinition(expression);
12             pointcutDefinition.setSource(parserContext.extractSource(element));
13             return pointcutDefinition;
14         }
15         else if (element.hasAttribute(POINTCUT_REF)) {
16             String pointcutRef = element.getAttribute(POINTCUT_REF);
17             if (!StringUtils.hasText(pointcutRef)) {
18                 parserContext.getReaderContext().error(
19                         "‘pointcut-ref‘ attribute contains empty value.", element, this.parseState.snapshot());
20                 return null;
21             }
22             return pointcutRef;
23         }
24         else {
25             parserContext.getReaderContext().error(
26                     "Must define one of ‘pointcut‘ or ‘pointcut-ref‘ on <advisor> tag.",
27                     element, this.parseState.snapshot());
28             return null;
29         }
30     }

第8行判断用户定义是不是pointcut属性,如果是那么就执行了以下代码

protected AbstractBeanDefinition createPointcutDefinition(String expression) {
     RootBeanDefinition beanDefinition = new RootBeanDefinition(AspectJExpressionPointcut.class);
     beanDefinition.setScope(BeanDefinition.SCOPE_PROTOTYPE);
     beanDefinition.setSynthetic(true);
     beanDefinition.getPropertyValues().add(EXPRESSION, expression);
     return beanDefinition;
}

创建了一个包装了AspectJExpressionPointcut类的BeanDefinition,并且预设声明周期为prototype,属性值EXPRESSION为用户在xml上定义的表达式

如果不是pointcut属性,是pointcut-ref属性,那么直接返回,我们又会到createAdviceDefinition方法继续往下

 1 Object pointcut = parsePointcutProperty(adviceElement, parserContext);
 2         if (pointcut instanceof BeanDefinition) {
 3             cav.addIndexedArgumentValue(POINTCUT_INDEX, pointcut);
 4             beanDefinitions.add((BeanDefinition) pointcut);
 5         }
 6         else if (pointcut instanceof String) {
 7             RuntimeBeanReference pointcutRef = new RuntimeBeanReference((String) pointcut);
 8             cav.addIndexedArgumentValue(POINTCUT_INDEX, pointcutRef);
 9             beanReferences.add(pointcutRef);
10         }
11 
12         cav.addIndexedArgumentValue(ASPECT_INSTANCE_FACTORY_INDEX, aspectFactoryDef);

如果用户定义在通知标签上的属性为pointcut,那么会走第二行内的代码,如果不是,就会走第2行的代码,如果走第6行代码,那么就直接加入通知类的第二个构造参数

如果是走第6行的代码,那么就对pointcutref封装成BeanReference。成为第二个构造参数,BeanReference有个键beanName的属性,用来表示它引用了那个bean,到时候要使用的时候就是BeanFactory中拿。

第12行定义了通知类的第三个构造参数,这个构造参数是前面定义的,它是一个持有SimpleBeanFactoryAwareAspectInstanceFactory类的BeanDefinition。

此时一个持有通知类的BeanDefinition就准备好了,返回到parseAdvice中

 

 1 // register the pointcut
 2             AbstractBeanDefinition adviceDef = createAdviceDefinition(
 3                     adviceElement, parserContext, aspectName, order, methodDefinition, aspectFactoryDef,
 4                     beanDefinitions, beanReferences);
 5 
 6             // configure the advisor
 7             RootBeanDefinition advisorDefinition = new RootBeanDefinition(AspectJPointcutAdvisor.class);
 8             advisorDefinition.setSource(parserContext.extractSource(adviceElement));
 9             advisorDefinition.getConstructorArgumentValues().addGenericArgumentValue(adviceDef);
10             if (aspectElement.hasAttribute(ORDER_PROPERTY)) {
11                 advisorDefinition.getPropertyValues().add(
12                         ORDER_PROPERTY, aspectElement.getAttribute(ORDER_PROPERTY));
13             }
14 
15             // register the final advisor
16             parserContext.getReaderContext().registerWithGeneratedName(advisorDefinition);

红色标识部分是我们返回会来的方法,继续往下看第7行,这里有创建了一个持有AspectJPointcutAdvisor类的BeanDefinition,这个AspectJPointcutAdvisor有这么一些属性

advice, pointcut,advice是一个AbstractAspectJAdvice抽象通知类型的属性,

技术分享

可以看到before,after等这些通知就是继承自它。

pointcut属性是一个Pointcut类型的属性,这里肯定是用来存AspectJExpressionPointcut子类。

 AspectJPointcutAdvisor类的构造器为AspectJPointcutAdvisor(AbstractAspectJAdvice advice)

 所以第九行果断给构造器定义了一个刚创建好的adviceDef参数

接着就执行了下面这段代码

1 public String registerWithGeneratedName(BeanDefinition beanDefinition) {
2         String generatedName = generateBeanName(beanDefinition);
3         getRegistry().registerBeanDefinition(generatedName, beanDefinition);
4         return generatedName;
5     }

传入的参数就是包装了AspectJPointcutAdvisor类的BeanDefinition,根据这个BeanDefinition生成名字形如org.springframework.aop.aspectj.AspectJPointcutAdvisor#1这样的名字,前面的类名,后面的数字表示这是创建的第几个AspectJPointcutAdvisor。这个无关紧要。

第三行将包装了AspectJPointcutAdvisor类的BeanDefinition添加到DefaultListableBeanFactory(BeanFactory子类)的beanDefinitionMap容器中

一切就绪后我们的方法返回到parseAspect方法

 1 AbstractBeanDefinition advisorDefinition = parseAdvice(
 2                             aspectName, i, aspectElement, (Element) node, parserContext, beanDefinitions, beanReferences);
 3                     beanDefinitions.add(advisorDefinition);
 4                 }
 5             }
 6 
 7             AspectComponentDefinition aspectComponentDefinition = createAspectComponentDefinition(
 8                     aspectElement, aspectId, beanDefinitions, beanReferences, parserContext);
 9             parserContext.pushContainingComponent(aspectComponentDefinition);
10 
11             List<Element> pointcuts = DomUtils.getChildElementsByTagName(aspectElement, POINTCUT);
12             for (Element pointcutElement : pointcuts) {
13                 parsePointcut(pointcutElement, parserContext);
14             }
15 
16             parserContext.popAndRegisterContainingComponent();

我们是从红色部分返回回来的。我们继续往下看第7行,它创建了一个AspectComponentDefinition对象,这个AspectComponentDefinition抛开父类,它有两个属性

private final BeanDefinition[] beanDefinitions;

private final BeanReference[] beanReferences;

它通过以下方法创建

private AspectComponentDefinition createAspectComponentDefinition(
            Element aspectElement, String aspectId, List<BeanDefinition> beanDefs,
            List<BeanReference> beanRefs, ParserContext parserContext) {

        BeanDefinition[] beanDefArray = beanDefs.toArray(new BeanDefinition[beanDefs.size()]);
        BeanReference[] beanRefArray = beanRefs.toArray(new BeanReference[beanRefs.size()]);
        Object source = parserContext.extractSource(aspectElement);
        return new AspectComponentDefinition(aspectId, beanDefArray, beanRefArray, source);
    }

它把装有AspectJPointcutAdvisor类的集合和装有BeanReference的集合设置进去。new出一个AspectComponentDefinition。也就是说这个AspectComponentDefinition类包含了再其内部定义的所有通知,所有使用到的ref指定的bean引用。

回到第11行,这里是指定到aspect标签内读取pointcut标签,第13行对其进行解析

 1 private AbstractBeanDefinition parsePointcut(Element pointcutElement, ParserContext parserContext) {
 2         String id = pointcutElement.getAttribute(ID);
 3         String expression = pointcutElement.getAttribute(EXPRESSION);
 4 
 5         AbstractBeanDefinition pointcutDefinition = null;
 6 
 7         try {
 8             this.parseState.push(new PointcutEntry(id));
 9             pointcutDefinition = createPointcutDefinition(expression);
10             pointcutDefinition.setSource(parserContext.extractSource(pointcutElement));
11 
12             String pointcutBeanName = id;
13             if (StringUtils.hasText(pointcutBeanName)) {
14                 parserContext.getRegistry().registerBeanDefinition(pointcutBeanName, pointcutDefinition);
15             }
16             else {
17                 pointcutBeanName = parserContext.getReaderContext().registerWithGeneratedName(pointcutDefinition);
18             }
19 
20             parserContext.registerComponent(
21                     new PointcutComponentDefinition(pointcutBeanName, pointcutDefinition, expression));
22         }
23         finally {
24             this.parseState.pop();
25         }
26 
27         return pointcutDefinition;
28     }

第2 3行分别获得它的id和表达式

第9行是创建一个持有AspectJExpressionPointcut class对象的BeanDefinition,这个其实在前面判断通知标签是否为pointcut属性还是pointcut-ref属性时探讨过。

第14行将创建出来的持有AspectJExpressionPointcut class对象的BeanDefinition注册到BeanFactory中的beanDefinitionMap容器中。

第20行向解析上下文中添加了一个PointcutComponentDefinition组件定义,这个切点组件定义和切面组件定义继承了同一个抽象组件类,它的自身的属性有pointcutBeanName,

pointcutDefinition,pointcutBeanName就是切点的id,pointcutDefinition就是持有AspectJExpressionPointcut 类的BeanDefinition。

 

 

到此aop命名空间处理器对aop标签的解析就结束了。

 所有的BeanDefinition都已经准备就绪,接下就是实例化这些BeanDefinition了,一直返回到ClasspathxmlApplication中,调用了以下方法

// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);

这个方法内部又调用了

// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();

 1 public void preInstantiateSingletons() throws BeansException {
 2         if (this.logger.isDebugEnabled()) {
 3             this.logger.debug("Pre-instantiating singletons in " + this);
 4         }
 5 
 6         // Iterate over a copy to allow for init methods which in turn register new bean definitions.
 7         // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
 8         List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
 9 
10         // Trigger initialization of all non-lazy singleton beans...
11         for (String beanName : beanNames) {
12             RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
13             if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
14                 if (isFactoryBean(beanName)) {
15                     final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
16                     boolean isEagerInit;
17                     if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
18                         isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
19                             @Override
20                             public Boolean run() {
21                                 return ((SmartFactoryBean<?>) factory).isEagerInit();
22                             }
23                         }, getAccessControlContext());
24                     }
25                     else {
26                         isEagerInit = (factory instanceof SmartFactoryBean &&
27                                 ((SmartFactoryBean<?>) factory).isEagerInit());
28                     }
29                     if (isEagerInit) {
30                         getBean(beanName);
31                     }
32                 }
33                 else {
34                     getBean(beanName);
35                 }
36             }
37         }
38 
39         // Trigger post-initialization callback for all applicable beans...
40         for (String beanName : beanNames) {
41             Object singletonInstance = getSingleton(beanName);
42             if (singletonInstance instanceof SmartInitializingSingleton) {
43                 final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
44                 if (System.getSecurityManager() != null) {
45                     AccessController.doPrivileged(new PrivilegedAction<Object>() {
46                         @Override
47                         public Object run() {
48                             smartSingleton.afterSingletonsInstantiated();
49                             return null;
50                         }
51                     }, getAccessControlContext());
52                 }
53                 else {
54                     smartSingleton.afterSingletonsInstantiated();
55                 }
56             }
57         }
58     }

第8行获取到所有的定义过的beanName,第11行对其进行遍历,并且进行是否是抽象的,是不是factorybean,是不是懒加载的,如果都不是直接跳到getBean()方法,getBean()方法内部又调用了

doBean方法

  1 protected <T> T doGetBean(
  2             final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
  3             throws BeansException {
  4 
  5         final String beanName = transformedBeanName(name);
  6         Object bean;
  7 
  8         // Eagerly check singleton cache for manually registered singletons.
  9         Object sharedInstance = getSingleton(beanName);
 10         if (sharedInstance != null && args == null) {
 11             if (logger.isDebugEnabled()) {
 12                 if (isSingletonCurrentlyInCreation(beanName)) {
 13                     logger.debug("Returning eagerly cached instance of singleton bean ‘" + beanName +
 14                             "‘ that is not fully initialized yet - a consequence of a circular reference");
 15                 }
 16                 else {
 17                     logger.debug("Returning cached instance of singleton bean ‘" + beanName + "");
 18                 }
 19             }
 20             bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
 21         }
 22 
 23         else {
 24             // Fail if we‘re already creating this bean instance:
 25             // We‘re assumably within a circular reference.
 26             if (isPrototypeCurrentlyInCreation(beanName)) {
 27                 throw new BeanCurrentlyInCreationException(beanName);
 28             }
 29 
 30             // Check if bean definition exists in this factory.
 31             BeanFactory parentBeanFactory = getParentBeanFactory();
 32             if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
 33                 // Not found -> check parent.
 34                 String nameToLookup = originalBeanName(name);
 35                 if (args != null) {
 36                     // Delegation to parent with explicit args.
 37                     return (T) parentBeanFactory.getBean(nameToLookup, args);
 38                 }
 39                 else {
 40                     // No args -> delegate to standard getBean method.
 41                     return parentBeanFactory.getBean(nameToLookup, requiredType);
 42                 }
 43             }
 44 
 45             if (!typeCheckOnly) {
 46                 markBeanAsCreated(beanName);
 47             }
 48 
 49             try {
 50                 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
 51                 checkMergedBeanDefinition(mbd, beanName, args);
 52 
 53                 // Guarantee initialization of beans that the current bean depends on.
 54                 String[] dependsOn = mbd.getDependsOn();
 55                 if (dependsOn != null) {
 56                     for (String dep : dependsOn) {
 57                         if (isDependent(beanName, dep)) {
 58                             throw new BeanCreationException(mbd.getResourceDescription(), beanName,
 59                                     "Circular depends-on relationship between ‘" + beanName + "‘ and ‘" + dep + "");
 60                         }
 61                         registerDependentBean(dep, beanName);
 62                         getBean(dep);
 63                     }
 64                 }
 65 
 66                 // Create bean instance.
 67                 if (mbd.isSingleton()) {
 68                     sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
 69                         @Override
 70                         public Object getObject() throws BeansException {
 71                             try {
 72                                 return createBean(beanName, mbd, args);
 73                             }
 74                             catch (BeansException ex) {
 75                                 // Explicitly remove instance from singleton cache: It might have been put there
 76                                 // eagerly by the creation process, to allow for circular reference resolution.
 77                                 // Also remove any beans that received a temporary reference to the bean.
 78                                 destroySingleton(beanName);
 79                                 throw ex;
 80                             }
 81                         }
 82                     });
 83                     bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
 84                 }
 85 
 86                 else if (mbd.isPrototype()) {
 87                     // It‘s a prototype -> create a new instance.
 88                     Object prototypeInstance = null;
 89                     try {
 90                         beforePrototypeCreation(beanName);
 91                         prototypeInstance = createBean(beanName, mbd, args);
 92                     }
 93                     finally {
 94                         afterPrototypeCreation(beanName);
 95                     }
 96                     bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
 97                 }
 98 
 99                 else {
100                     String scopeName = mbd.getScope();
101                     final Scope scope = this.scopes.get(scopeName);
102                     if (scope == null) {
103                         throw new IllegalStateException("No Scope registered for scope name ‘" + scopeName + "");
104                     }
105                     try {
106                         Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
107                             @Override
108                             public Object getObject() throws BeansException {
109                                 beforePrototypeCreation(beanName);
110                                 try {
111                                     return createBean(beanName, mbd, args);
112                                 }
113                                 finally {
114                                     afterPrototypeCreation(beanName);
115                                 }
116                             }
117                         });
118                         bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
119                     }
120                     catch (IllegalStateException ex) {
121                         throw new BeanCreationException(beanName,
122                                 "Scope ‘" + scopeName + "‘ is not active for the current thread; consider " +
123                                 "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
124                                 ex);
125                     }
126                 }
127             }
128             catch (BeansException ex) {
129                 cleanupAfterBeanCreationFailure(beanName);
130                 throw ex;
131             }
132         }
133 
134         // Check if required type matches the type of the actual bean instance.
135         if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
136             try {
137                 return getTypeConverter().convertIfNecessary(bean, requiredType);
138             }
139             catch (TypeMismatchException ex) {
140                 if (logger.isDebugEnabled()) {
141                     logger.debug("Failed to convert bean ‘" + name + "‘ to required type ‘" +
142                             ClassUtils.getQualifiedName(requiredType) + "", ex);
143                 }
144                 throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
145             }
146         }
147         return (T) bean;
148     }

第5行对beanName进行了转换,因为我们传进去的参数可能是别名。

第9行对非懒加载的bean进行实例化。

第55行对依赖进行判断,如果有依赖还要进行循环依赖判断,构造器循环依赖是无法解决的会直接抛出异常,setter方法依赖就不会。

 1 // Create bean instance.
 2                 if (mbd.isSingleton()) {
 3                     sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
 4                         @Override
 5                         public Object getObject() throws BeansException {
 6                             try {
 7                                 return createBean(beanName, mbd, args);
 8                             }
 9                             catch (BeansException ex) {
10                                 // Explicitly remove instance from singleton cache: It might have been put there
11                                 // eagerly by the creation process, to allow for circular reference resolution.
12                                 // Also remove any beans that received a temporary reference to the bean.
13                                 destroySingleton(beanName);
14                                 throw ex;
15                             }
16                         }
17                     });
18                     bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
19                 }

第3行

 1 public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
 2         Assert.notNull(beanName, "‘beanName‘ must not be null");
 3         synchronized (this.singletonObjects) {
 4             Object singletonObject = this.singletonObjects.get(beanName);
 5             if (singletonObject == null) {
 6                 if (this.singletonsCurrentlyInDestruction) {
 7                     throw new BeanCreationNotAllowedException(beanName,
 8                             "Singleton bean creation not allowed while singletons of this factory are in destruction " +
 9                             "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
10                 }
11                 if (logger.isDebugEnabled()) {
12                     logger.debug("Creating shared instance of singleton bean ‘" + beanName + "");
13                 }
14                 beforeSingletonCreation(beanName);
15                 boolean newSingleton = false;
16                 boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
17                 if (recordSuppressedExceptions) {
18                     this.suppressedExceptions = new LinkedHashSet<Exception>();
19                 }
20                 try {
21                     singletonObject = singletonFactory.getObject();
22                     newSingleton = true;
23                 }
24                 catch (IllegalStateException ex) {
25                     // Has the singleton object implicitly appeared in the meantime ->
26                     // if yes, proceed with it since the exception indicates that state.
27                     singletonObject = this.singletonObjects.get(beanName);
28                     if (singletonObject == null) {
29                         throw ex;
30                     }
31                 }
32                 catch (BeanCreationException ex) {
33                     if (recordSuppressedExceptions) {
34                         for (Exception suppressedException : this.suppressedExceptions) {
35                             ex.addRelatedCause(suppressedException);
36                         }
37                     }
38                     throw ex;
39                 }
40                 finally {
41                     if (recordSuppressedExceptions) {
42                         this.suppressedExceptions = null;
43                     }
44                     afterSingletonCreation(beanName);
45                 }
46                 if (newSingleton) {
47                     addSingleton(beanName, singletonObject);
48                 }
49             }
50             return (singletonObject != NULL_OBJECT ? singletonObject : null);
51         }
52     }

第四行先冲到BeanFactory的singletonObjects容器中查看这个类是否已经被创建了。

第21行调用了一下代码

new ObjectFactory<Object>() {
    @Override
    public Object getObject() throws BeansException {
       try {
          return createBean(beanName, mbd, args);
}

继续跟踪createBean方法,假设当前要创建的对象是AspectJAwareAdvisorAutoProxyCreator类的实例

那么beanName表示对应这个BeanDefinition的id名,mbd就是包装了AspectJAwareAdvisorAutoProxyCreator的BeanDefinition。

 1 protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
 2         if (logger.isDebugEnabled()) {
 3             logger.debug("Creating instance of bean ‘" + beanName + "");
 4         }
 5         RootBeanDefinition mbdToUse = mbd;
 6 
 7         // Make sure bean class is actually resolved at this point, and
 8         // clone the bean definition in case of a dynamically resolved Class
 9         // which cannot be stored in the shared merged bean definition.
10         Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
11         if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
12             mbdToUse = new RootBeanDefinition(mbd);
13             mbdToUse.setBeanClass(resolvedClass);
14         }
15 
16         // Prepare method overrides.
17         try {
18             mbdToUse.prepareMethodOverrides();
19         }
20         catch (BeanDefinitionValidationException ex) {
21             throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
22                     beanName, "Validation of method overrides failed", ex);
23         }
24 
25         try {
26             // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
27             Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
28             if (bean != null) {
29                 return bean;
30             }
31         }
32         catch (Throwable ex) {
33             throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
34                     "BeanPostProcessor before instantiation of bean failed", ex);
35         }
36 
37         Object beanInstance = doCreateBean(beanName, mbdToUse, args);
38         if (logger.isDebugEnabled()) {
39             logger.debug("Finished creating instance of bean ‘" + beanName + "");
40         }
41         return beanInstance;
42     }

第10行获取这个BeanDefinition内持有的class对象,所以这里是AspectJAwareAdvisorAutoProxyCreator类的class对象

第18行是准备方法覆盖,这个一般在使用了lookup-method,replace-method的时候使用。这里明显为空

第27行检查是否实现了InstantiationAwareBeanPostProcessor接口,如果是,这里会调用实现的postProcessBeforeInstantiation方法。

第37行方法中调用了instanceWrapper = createBeanInstance(beanName, mbd, args);方法

 1 protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
 2         // Make sure bean class is actually resolved at this point.
 3         Class<?> beanClass = resolveBeanClass(mbd, beanName);
 4 
 5         if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
 6             throw new BeanCreationException(mbd.getResourceDescription(), beanName,
 7                     "Bean class isn‘t public, and non-public access not allowed: " + beanClass.getName());
 8         }
 9 
10         if (mbd.getFactoryMethodName() != null)  {
11             return instantiateUsingFactoryMethod(beanName, mbd, args);
12         }
13 
14         // Shortcut when re-creating the same bean...
15         boolean resolved = false;
16         boolean autowireNecessary = false;
17         if (args == null) {
18             synchronized (mbd.constructorArgumentLock) {
19                 if (mbd.resolvedConstructorOrFactoryMethod != null) {
20                     resolved = true;
21                     autowireNecessary = mbd.constructorArgumentsResolved;
22                 }
23             }
24         }
25         if (resolved) {
26             if (autowireNecessary) {
27                 return autowireConstructor(beanName, mbd, null, null);
28             }
29             else {
30                 return instantiateBean(beanName, mbd);
31             }
32         }
33 
34         // Need to determine the constructor...
35         Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
36         if (ctors != null ||
37                 mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
38                 mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
39             return autowireConstructor(beanName, mbd, ctors, args);
40         }
41 
42         // No special handling: simply use no-arg constructor.
43         return instantiateBean(beanName, mbd);
44     }

第5行判断这个bean是不是public的,有没有访问权限,没有就抛异常

第10行是判断它是否有工厂方法,如果有工厂方法,就用工厂方法创建对象。

第35确定其是否需要构造器注入,如果是的话,那么会执行第39行,构造器注入的方式,否则直接到第43行,用无参构造器处理

进入这个instantiateBean方法

 1 protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
 2         try {
 3             Object beanInstance;
 4             final BeanFactory parent = this;
 5             if (System.getSecurityManager() != null) {
 6                 beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
 7                     @Override
 8                     public Object run() {
 9                         return getInstantiationStrategy().instantiate(mbd, beanName, parent);
10                     }
11                 }, getAccessControlContext());
12             }
13             else {
14                 beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
15             }
16             BeanWrapper bw = new BeanWrapperImpl(beanInstance);
17             initBeanWrapper(bw);
18             return bw;
19         }
20         catch (Throwable ex) {
21             throw new BeanCreationException(
22                     mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
23         }
24     }

第14行getInstantiationStrategy()获取实例化策略,有SimpleInstantiationStrategy,CglibSubclassingInstantiationStrategy策略

这里我们假设是CglibSubclassingInstantiationStrategy策略,接下来调用了这个策略的instantiate方法,我们这里使用的CglibSubclassingInstantiationStrategy策略。进去看看吧

 1 public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {
 2         // Don‘t override the class with CGLIB if no overrides.
 3         if (bd.getMethodOverrides().isEmpty()) {
 4             Constructor<?> constructorToUse;
 5             synchronized (bd.constructorArgumentLock) {
 6                 constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
 7                 if (constructorToUse == null) {
 8                     final Class<?> clazz = bd.getBeanClass();
 9                     if (clazz.isInterface()) {
10                         throw new BeanInstantiationException(clazz, "Specified class is an interface");
11                     }
12                     try {
13                         if (System.getSecurityManager() != null) {
14                             constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor<?>>() {
15                                 @Override
16                                 public Constructor<?> run() throws Exception {
17                                     return clazz.getDeclaredConstructor((Class[]) null);
18                                 }
19                             });
20                         }
21                         else {
22                             constructorToUse =    clazz.getDeclaredConstructor((Class[]) null);
23                         }
24                         bd.resolvedConstructorOrFactoryMethod = constructorToUse;
25                     }
26                     catch (Throwable ex) {
27                         throw new BeanInstantiationException(clazz, "No default constructor found", ex);
28                     }
29                 }
30             }
31             return BeanUtils.instantiateClass(constructorToUse);
32         }
33         else {
34             // Must generate CGLIB subclass.
35             return instantiateWithMethodInjection(bd, beanName, owner);
36         }
37     }

第9行判断这个类是不是接口,如果是接口,那就要报错,不能实例化

第22行获取到这个class的无参构造器

第31行代码

 1 public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
 2         Assert.notNull(ctor, "Constructor must not be null");
 3         try {
 4             ReflectionUtils.makeAccessible(ctor);
 5             return ctor.newInstance(args);
 6         }
 7         catch (InstantiationException ex) {
 8             throw new BeanInstantiationException(ctor, "Is it an abstract class?", ex);
 9         }
10         catch (IllegalAccessException ex) {
11             throw new BeanInstantiationException(ctor, "Is the constructor accessible?", ex);
12         }
13         catch (IllegalArgumentException ex) {
14             throw new BeanInstantiationException(ctor, "Illegal arguments for constructor", ex);
15         }
16         catch (InvocationTargetException ex) {
17             throw new BeanInstantiationException(ctor, "Constructor threw exception", ex.getTargetException());
18         }
19     }

第4行判断这个构造方法是否可见,不可见就设置为可见,然后使用构造器构造对象

就这样,对象就被创建了。创建了这个类的实例后还有注入相应的非依赖属性,比如一些原始类型的属性

spring使用了JDK自带的PropertyDescriptor类,通过获取writeMethod将值设置进去。

这个方法在BeanWrapperImpl类中定义,部分代码

public void setValue(final Object object, Object valueToApply) throws Exception {
       final Method writeMethod = (this.pd instanceof GenericTypeAwarePropertyDescriptor ?
       ((GenericTypeAwarePropertyDescriptor) this.pd).getWriteMethodForActualAccess() :
       this.pd.getWriteMethod());

获取到了它对应属性的set方法。

调用writeMethod.invoke(getWrappedInstance(), value);将值设置进去

这个类在设置好值之后,会判断是否需要进行初始化,由于这个类实现了InstantiationAwareBeanPostProcessor接口,所以最后还会调用

postProcessAfterInitialization方法

最后将创建好的bean放到singletonObjects中

之前创建了AspectJAwareAdvisorAutoProxyCreator的实例,它实现了BeanPostProcessor接口,所以在BeanFactory中的beanPostProcessors集合中会保存它。

也就是说在后续创建其他的bean的过程中都或调用AspectJAwareAdvisorAutoProxyCreator的postProcessBeforeInitialization和postProcessAfterInitialization(Object, String)方法

 1 public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
 2         Object cacheKey = getCacheKey(beanClass, beanName);
 3 
 4         if (beanName == null || !this.targetSourcedBeans.contains(beanName)) {
 5             if (this.advisedBeans.containsKey(cacheKey)) {
 6                 return null;
 7             }
 8             if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
 9                 this.advisedBeans.put(cacheKey, Boolean.FALSE);
10                 return null;
11             }
12         }
13 
14         // Create proxy here if we have a custom TargetSource.
15         // Suppresses unnecessary default instantiation of the target bean:
16         // The TargetSource will handle target instances in a custom fashion.
17         if (beanName != null) {
18             TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
19             if (targetSource != null) {
20                 this.targetSourcedBeans.add(beanName);
21                 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
22                 Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
23                 this.proxyTypes.put(cacheKey, proxy.getClass());
24                 return proxy;
25             }
26         }
27 
28         return null;
29     }

重点看到第8行shouldSkip方法

 1 protected boolean shouldSkip(Class<?> beanClass, String beanName) {
 2         // TODO: Consider optimization by caching the list of the aspect names
 3         List<Advisor> candidateAdvisors = findCandidateAdvisors();
 4         for (Advisor advisor : candidateAdvisors) {
 5             if (advisor instanceof AspectJPointcutAdvisor) {
 6                 if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) {
 7                     return true;
 8                 }
 9             }
10         }
11         return super.shouldSkip(beanClass, beanName);
12     }

第三行表示去获取候选的通知器。调用了advisors.add(this.beanFactory.getBean(name, Advisor.class));方法

其中的getBean方法很眼熟,跟上面创建bean的操作一样,获取到了所有的advisor。

将获取到advisor遍历,取出当前advisor中的advice拿到它对应的aspectName和当前要创建的bean的beanName进行equals,如果相等,那就返回TRUE,并将使用当前beanClass生成的CacheKey保存到AspectJAwareAdvisorAutoProxyCreator父类的一个叫做advisedBeans的map集合中,为什么这么做呢?因为用户定义的切面可能有多个。不符合的bean就跳过(也就是遇到不是aspect的bean跳过)

 

一切准备就绪,开始创建代理对象

调用了AspectJAwareAdvisorAutoProxyCreator的

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
   if (bean != null) {
      Object cacheKey = getCacheKey(bean.getClass(), beanName);
       if (!this.earlyProxyReferences.contains(cacheKey)) {
      return wrapIfNecessary(bean, beanName, cacheKey);
    }
   }
   return bean;
}

我们进到wrapIfNecessary看看

1 // Create proxy if we have advice.
2         Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
3         if (specificInterceptors != DO_NOT_PROXY) {
4             this.advisedBeans.put(cacheKey, Boolean.TRUE);
5             Object proxy = createProxy(
6                     bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
7             this.proxyTypes.put(cacheKey, proxy.getClass());
8             return proxy;
9         }

进入第2行代码

1 protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
2         List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
3         if (advisors.isEmpty()) {
4             return DO_NOT_PROXY;
5         }
6         return advisors.toArray();
7     }

第2行代码通过当前类和类名寻找匹配的通知器

findEligibleAdvisors:
1 protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
2         List<Advisor> candidateAdvisors = findCandidateAdvisors();
3         List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
4         extendAdvisors(eligibleAdvisors);
5         if (!eligibleAdvisors.isEmpty()) {
6             eligibleAdvisors = sortAdvisors(eligibleAdvisors);
7         }
8         return eligibleAdvisors;
9     }

第二行获取到了所有候选的通知器

第三行获取到匹配当前bean的通知器

内部调用了AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);这个方法

内部又调用了canApply(pca.getPointcut(), targetClass, hasIntroductions);方法

 1 for (Class<?> clazz : classes) {
 2             Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
 3             for (Method method : methods) {
 4                 if ((introductionAwareMethodMatcher != null &&
 5                         introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
 6                         methodMatcher.matches(method, targetClass)) {
 7                     return true;
 8                 }
 9             }
10         }

通过反射拿到当前类的所有方法,使用一个方法匹配器去配置当前方法是否可以匹配切点

如果匹配将对应的通知器保存起来,最后返回回到下面一段代码

Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));

最后我们看到createAopProxy犯法,这个方法的代码
 1 public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
 2         if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
 3             Class<?> targetClass = config.getTargetClass();
 4             if (targetClass == null) {
 5                 throw new AopConfigException("TargetSource cannot determine target class: " +
 6                         "Either an interface or a target is required for proxy creation.");
 7             }
 8             if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
 9                 return new JdkDynamicAopProxy(config);
10             }
11             return new ObjenesisCglibAopProxy(config);
12         }
13         else {
14             return new JdkDynamicAopProxy(config);
15         }
16     }

第8行判断它是否实现了接口,如果实现了接口,那么就使用JDK的动态代理

否则使用第11行的cglib代理

接下类调用了getProxy方法,里面是我们属性代理创建过程,这里拿cglib为例

 1 // Configure CGLIB Enhancer...
 2             Enhancer enhancer = createEnhancer();
 3             if (classLoader != null) {
 4                 enhancer.setClassLoader(classLoader);
 5                 if (classLoader instanceof SmartClassLoader &&
 6                         ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
 7                     enhancer.setUseCache(false);
 8                 }
 9             }
10             enhancer.setSuperclass(proxySuperClass);
11             enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
12             enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
13             enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
14 
15             Callback[] callbacks = getCallbacks(rootClass);
16             Class<?>[] types = new Class<?>[callbacks.length];
17             for (int x = 0; x < types.length; x++) {
18                 types[x] = callbacks[x].getClass();
19             }
20             // fixedInterceptorMap only populated at this point, after getCallbacks call above
21             enhancer.setCallbackFilter(new ProxyCallbackFilter(
22                     this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
23             enhancer.setCallbackTypes(types);
24 
25             // Generate the proxy class and create a proxy instance.
26             return createProxyClassAndInstance(enhancer, callbacks);

看到第26行

createProxyClassAndInstance这个方法有这么一行代码

Class<?> proxyClass = enhancer.createClass();

这行代码用debug跟进去之后,发现最后它创建了实现了MethodInterceptor的方法拦截器,比如像下面这个

 

public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
   this.advice = advice;
}

所有的通知最后都会被封装成一个MethodInterceptor。

 

 1 public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
 2         List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>(3);
 3         Advice advice = advisor.getAdvice();
 4         if (advice instanceof MethodInterceptor) {
 5             interceptors.add((MethodInterceptor) advice);
 6         }
 7         for (AdvisorAdapter adapter : this.adapters) {
 8             if (adapter.supportsAdvice(advice)) {
 9                 interceptors.add(adapter.getInterceptor(advisor));
10             }
11         }
12         if (interceptors.isEmpty()) {
13             throw new UnknownAdviceTypeException(advisor.getAdvice());
14         }
15         return interceptors.toArray(new MethodInterceptor[interceptors.size()]);
16     }

将所有的通知都打包成interceptor之后变成数组返回

MethodInterceptor接口只有一个方法Object invoke(MethodInvocation invocation) throws Throwable;

拿其中一个MethodBeforeAdviceInterceptor方法分析一下他的invoke方法

1 public Object invoke(MethodInvocation mi) throws Throwable {
2         this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
3         return mi.proceed();
4     }

 

第2行表示在执行目标方法前执行了这个通知类方法

当给每一个方法确定了匹配的通知拦截器后,准备工作也就完成了。

 

当我们去BeanFactory获取对象的时候,比如我们获取的是一个叫做UserService的类,这个service被应用了aop,所以很显然我们获取到的是一个代理类

我们用这个代理类去调用一个被增强的方法

加入代码是这样写的UserService service = beanFactory.getBean(UserService.class);

service.save();

从这里开始

当调用了这个方法后我们进入了一个DynamicAdvisedInterceptor类的intercept方法

 1     public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
 2             Object oldProxy = null;
 3             boolean setProxyContext = false;
 4             Class<?> targetClass = null;
 5             Object target = null;
 6             try {
 7                 if (this.advised.exposeProxy) {
 8                     // Make invocation available if necessary.
 9                     oldProxy = AopContext.setCurrentProxy(proxy);
10                     setProxyContext = true;
11                 }
12                 // May be null. Get as late as possible to minimize the time we
13                 // "own" the target, in case it comes from a pool...
14                 target = getTarget();
15                 if (target != null) {
16                     targetClass = target.getClass();
17                 }
18                 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
19                 Object retVal;
20                 // Check whether we only have one InvokerInterceptor: that is,
21                 // no real advice, but just reflective invocation of the target.
22                 if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
23                     // We can skip creating a MethodInvocation: just invoke the target directly.
24                     // Note that the final invoker must be an InvokerInterceptor, so we know
25                     // it does nothing but a reflective operation on the target, and no hot
26                     // swapping or fancy proxying.
27                     Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
28                     retVal = methodProxy.invoke(target, argsToUse);
29                 }
30                 else {
31                     // We need to create a method invocation...
32                     retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
33                 }
34                 retVal = processReturnType(proxy, target, method, retVal);
35                 return retVal;
36             }
37             finally {
38                 if (target != null) {
39                     releaseTarget(target);
40                 }
41                 if (setProxyContext) {
42                     // Restore old proxy.
43                     AopContext.setCurrentProxy(oldProxy);
44                 }
45             }
46         }

第14行获取目标代理类

第18行获取符合代理目标的拦截器链。也就是一个集合装了一堆符合条件的拦截器,比如前置通知拦截器,后置通知拦截器

第32行创建一个CglibMethodInvocation的实例,并且调用它的proceed方法

 1 public Object proceed() throws Throwable {
 2         //    We start with an index of -1 and increment early.
 3         if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
 4             return invokeJoinpoint();
 5         }
 6 
 7         Object interceptorOrInterceptionAdvice =
 8                 this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
 9         if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
10             // Evaluate dynamic method matcher here: static part will already have
11             // been evaluated and found to match.
12             InterceptorAndDynamicMethodMatcher dm =
13                     (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
14             if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
15                 return dm.interceptor.invoke(this);
16             }
17             else {
18                 // Dynamic matching failed.
19                 // Skip this interceptor and invoke the next in the chain.
20                 return proceed();
21             }
22         }
23         else {
24             // It‘s an interceptor, so we just invoke it: The pointcut will have
25             // been evaluated statically before this object was constructed.
26             return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
27         }
28     }

 

第3行代码查看当前下标和当前拦截器链的个数减一是否相等了,如果相等了,那么就调用被代理的目标方法,

这里使用了一个currentInterceptorIndex来表示当前已经调用到了哪个拦截器
第8行获取当前下标的拦截器 ,并且调用它的invoke方法,把自身也传进去
假设当前的拦截器是AspectJAfterAdvice拦截器,那么它的invoke方法如下
1 public Object invoke(MethodInvocation mi) throws Throwable {
2         try {
3             return mi.proceed();
4         }
5         finally {
6             invokeAdviceMethod(getJoinPointMatch(), null, null);
7         }
8     }

在mi.proceed()结束后才调用通知方法,所以可以想象,before通知的只要把调用通知的方法写在mi.proceed()前面,after通知把通知方法写在后面,那不就做到在原始方法前面条用逻辑和后面调用逻辑了吗?而且你不觉得这种调用方式很想责任链模式吗?那throwing通知是怎么做的呢?throwing通知当然是使用try catch将mi.process()包裹,然后在catch中写逻辑。那returning

呢?returning就在mi.process()返回值后写逻辑。

 

这时候我们想啊。事物是怎么配置的呢?事物也一样都是使用的aop,它只不过在调用mi.process()方法的前面去DataSource中获取到了一个连接,将这个连接像jdbc一样操作,设置它不自动提交,设置隔离机制等等把获取到的线程保存到本地线程中(ThreadLocal中),然后在mi.process()方法上使用了try catch,一旦发生异常,并且默认异常为runtimeException或者Error,那么就会滚。这里提到了将连接保存到本地线程中,所以在使用hibernate的时候我们应当使用getCurrentSession(),而不是openSession。

 

总结:spring aop的原理就是使用动态代理产生一个代理对象,然后通过代理对象去调用了一个methodInvocation,这个methodInvocation持有通知的拦截器链的集合,还有一个表示当前调用到了哪一个拦截器的下标。还有目标方法,和目标对象,目标方法的参数。就像web中的过滤器一样运行(实际上过滤器链也是这个原理)。

 

spring aop(四)

标签:join   record   oop   ext   manual   post   require   bean   cache   

原文地址:http://www.cnblogs.com/honger/p/7294318.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!