spring aop(四)

直接找到解析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中的过滤器一样运行(实际上过滤器链也是这个原理)。

时间: 2024-10-01 04:46:20

spring aop(四)的相关文章

Spring AOP四种实现方式Demo详解与相关知识探究

一.前言 在网络上看到一篇博客Spring实现AOP的4种方式,博主写的很通俗易懂,但排版实在抓狂,对于我这么一个对排版.代码格式有强迫症的人来说,实在是不能忍受~~~~(>_<)~~~~. 我亲手实现了一遍,重新整理,加上了一些不易关注到的细节.漏掉的知识,以及自己对AOP的一些理解,写成这篇博客. 二.AOP相关概念 (1)AOP是什么?AOP与拦截器的区别? 太抽象的不说,如果你知道Struts2的拦截器,拦截器就是应用的AOP的思想,它用于拦截Action以进行一些预处理或结果处理.而

Spring AOP小记

一.概述 在通常的开发过程中,我们调用的顺序通常是controller->service-dao,其中,service中包含着太多的业务逻辑,并且还要不断调用dao来实现自身的业务逻辑,经常会导致业务耗时过久,在aop出现之前,方式一般是在函数中开始写一个startTime,结尾再写一个endTime来查看执行该函数的耗时,过多的使用此类方式会导致代码的耦合性太高,不利于管理,于是,AOP(面向切面)出现了.AOP关注的是横向的,而OOP的是纵向. Spring自2.0版本开始采用@Aspect

Spring AOP实现方式四之注入式AspectJ切面【附源码】

现在我们要讲的是第四种AOP实现之注入式AspectJ切面 通过简单的配置就可以实现AOP了. 源码结构: 1.首先我们新建一个接口,love 谈恋爱接口. package com.spring.aop; /** * 谈恋爱接口 * * @author Administrator * */ public interface Love { /* * 谈恋爱方法 */ void fallInLove(); } .csharpcode, .csharpcode pre { font-size: sma

Spring系列(四):Spring AOP详解

一.AOP是什么 AOP(面向切面编程),可以说是一种编程思想,其中的Spring AOP和AspectJ都是现实了这种编程思想.相对OOP(面向过程编程)来说,提供了另外一种编程方式,对于OOP过程中产生的横切性问题,这些横切性与业务无关,可以通过预编译方式和运行期动态代理来实现.比如可以应用在:日志记录.性能监控.事务管理等. 二.AOP的基本概念 Aspect(切面):通常来说是一个类,里面定义了切点和通知,Spring AOP中可以用@AspectJ来标注这个类是切面: Join poi

【Spring AOP】切入点表达式(四)

一.切入点指示符 切入点指示符用来指示切入点表达式目的,在Spring AOP中目前只有执行方法这一个连接点,Spring AOP支持的AspectJ切入点指示符如下: execution:用于匹配方法执行的连接点: within:用于匹配指定的类及其子类中的所有方法. this:匹配可以向上转型为this指定的类型的代理对象中的所有方法. target:匹配可以向上转型为target指定的类型的目标对象中的所有方法. args:用于匹配运行时传入的参数列表的类型为指定的参数列表类型的方法: @

浅谈Spring(四)AOP实例

在<浅谈Spring(三)AOP原理>中我详细的介绍了AOP的基本概念和实现原理,这里给出代码示例. 一.XML方式 1. TestAspect:切面类 package com.spring.aop; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; public class TestAspect { public void doAfter(JoinPoint jp) { System

spring aop 原理

http://blog.csdn.net/moreevan/article/details/11977115 Spring AOP 实现原理 2013-09-24 15:23 79554人阅读 评论(11) 收藏 举报  分类: spring(2)  版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] 什么是AOP AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)

spring AOP和通知

1.  spring的通知 1.1.  AOP的概念 切面(Aspect):一个关注点的模块化,这个关注点可能会横切多个对象.事务管理是J2EE应用中一个关于横切关注点的很好的例子.在Spring AOP中,切面可以使用基于模式或者基于注解的方式来实现. 连接点(Joinpoint):在程序执行过程中某个特定的点,比如某方法调用的时候或者处理异常的时候.在Spring AOP中,一个连接点总是表示一个方法的执行. 通知(Advice):在切面的某个特定的连接点上执行的动作.其中包括了"aroun

JavaEE学习之Spring aop

一.基本概念 AOP——Aspect-Oriented Programming,面向切面编程,它是spring框架的一个重要组成部分.一般的业务逻辑都有先后关系,我们可以理解为纵向关系,而AOP关注的是横向关系,每一个关注点可以理解为一个横切面.例如我们的大部分代码都会涉及到日志记录,很多的数据库操作都会涉及到事务的创建和提交.那么从横向关注这些逻辑,他们都一个个的切面. AOP技术的具体实现,可以通过动态代理技术或者是在程序编译期间进行静态的"织入"方式.AOP经常使用的场景包括:日