zoukankan      html  css  js  c++  java
  • 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中的过滤器一样运行(实际上过滤器链也是这个原理)。

  • 相关阅读:
    一、javaSE (十三)StringBuffer类、数组高级以及 Arrays类、Integer类、Character类
    一、javaSE (十二)scanner的使用、 String类的概述和使用
    一、javaSE (十一)objest类
    一、javaSE (十)形参和返回值、包、导包、权限修饰符、常见修饰符、内部类
    一、javaSE (九)final、多态、抽象类、接口
    一、javaSE (八)类的继承、方法重写
    一、javaSE (七)类的封装、关键字
    JBOSS7搭载EJB3之消息驱动Bean
    JBOSS7搭载EJB3之实体Bean
    jboss7搭载EJB3之简单会话BEAN与依赖注入jboss数据源
  • 原文地址:https://www.cnblogs.com/honger/p/7294318.html
Copyright © 2011-2022 走看看