Spring AOP源码篇三之 xml配置

简单代码示例, 了解Spring AOP基于xml的基本用法

xml配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xmlns:aop="http://www.springframework.org/schema/aop"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

	<bean id="aopAdvice" class="org.spring.aop.parse.advice.AopAdvice"></bean>

	<!-- 第一种配置方式 -->
	<aop:config proxy-target-class="false">
		<aop:aspect ref="aopAdvice">
			<aop:pointcut expression="execution(* org.spring.aop.parse.service..*.*(..))" id="callAt"/>
			<aop:around method="around" pointcut-ref="callAt"/>
			<aop:before method="before" pointcut="execution(* org.spring.aop.parse.service..*.*(..))"/>
			<aop:after method="after" pointcut="execution(* org.spring.aop.parse.service..*.*(..))"/>
		</aop:aspect>
	</aop:config>

	<!--<aop:config proxy-target-class="true">
		<aop:pointcut id="callAt" expression="execution(* org.spring.aop.service..*.*(..))"></aop:pointcut>
	</aop:config>-->

	<!-- 第二种配置方式 -->
	<bean id="logAdvice" class="org.spring.aop.parse.advice.LogAdvice"></bean>
	<aop:config proxy-target-class="false">
		<!--<aop:pointcut id="callAt" expression="execution(* org.spring.aop.service..*.*(..))"></aop:pointcut>-->
		<aop:advisor id="logAdvisor" advice-ref="logAdvice" pointcut="execution(* org.spring.aop.parse.service..*.*(..))"></aop:advisor>
		<!--<aop:advisor id="logAdvisor" advice-ref="logAdvice" pointcut-ref="callAt"></aop:advisor>-->
	</aop:config>

	<!-- 第三种引介增强 -->
	<!--<bean id="addService" class="org.spring.aop.parse.advice.AddService"/>-->
	<aop:config proxy-target-class="false">
	<aop:aspect ref="aopAdvice">
		<aop:declare-parents types-matching="org.spring.aop.parse.service.*" implement-interface="org.spring.aop.parse.advice.IAddService" default-impl="org.spring.aop.parse.advice.AddService"/>
		<!--<aop:declare-parents types-matching="org.spring.aop.parse.service.*" implement-interface="org.spring.aop.parse.advice.IAddService" delegate-ref="addService"/>-->
	</aop:aspect>
	</aop:config>


	<bean id="userService" class="org.spring.aop.parse.service.UserService"/>
</beans>

测试代码:

package org.spring.aop.parse;

import org.spring.aop.parse.advice.IAddService;
import org.spring.aop.parse.service.IUserService;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainTest {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-config-aop.xml");
        applicationContext.start();

        Object objService = applicationContext.getBean("userService");
        IUserService userService = (IUserService)objService;
        userService.say();

        System.out.println("\n-------------对目标对象引介增强-----------------\n");

        IAddService addService = (IAddService)objService;
        addService.doSomething();

        applicationContext.stop();
    }
}

执行结果:

=======================开始从源码分析过程========================
从handler中找到标签对应的NamespaceHandler:AopNamespaceHandler
从AopNamespaceHandler中找到标签对应的BeanDefinitionParser:ConfigBeanDefinitionParser,ConfigBeanDefinitionParser就是源码第一个关键入口

ConfigBeanDefinitionParser:将xml配置准换为Advisor的BeanDefinition,在ApplicationContext的refresh()中自动调用,将BeanDefinition转为Advisor对象。
package org.springframework.aop.config;

import java.util.ArrayList;
import java.util.List;

import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import org.springframework.aop.aspectj.AspectJAfterAdvice;
import org.springframework.aop.aspectj.AspectJAfterReturningAdvice;
import org.springframework.aop.aspectj.AspectJAfterThrowingAdvice;
import org.springframework.aop.aspectj.AspectJAroundAdvice;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.aspectj.AspectJMethodBeforeAdvice;
import org.springframework.aop.aspectj.AspectJPointcutAdvisor;
import org.springframework.aop.aspectj.DeclareParentsAdvisor;
import org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanReference;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.config.RuntimeBeanNameReference;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
import org.springframework.beans.factory.parsing.ParseState;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;


public class ConfigBeanDefinitionParser implements BeanDefinitionParser {
    private static final String ASPECT = "aspect";
    private static final String EXPRESSION = "expression";
    private static final String ID = "id";
    private static final String POINTCUT = "pointcut";
    private static final String ADVICE_BEAN_NAME = "adviceBeanName";
    private static final String ADVISOR = "advisor";
    private static final String ADVICE_REF = "advice-ref";
    private static final String POINTCUT_REF = "pointcut-ref";
    private static final String REF = "ref";
    private static final String BEFORE = "before";
    private static final String DECLARE_PARENTS = "declare-parents";
    private static final String TYPE_PATTERN = "types-matching";
    private static final String DEFAULT_IMPL = "default-impl";
    private static final String DELEGATE_REF = "delegate-ref";
    private static final String IMPLEMENT_INTERFACE = "implement-interface";
    private static final String AFTER = "after";
    private static final String AFTER_RETURNING_ELEMENT = "after-returning";
    private static final String AFTER_THROWING_ELEMENT = "after-throwing";
    private static final String AROUND = "around";
    private static final String RETURNING = "returning";
    private static final String RETURNING_PROPERTY = "returningName";
    private static final String THROWING = "throwing";
    private static final String THROWING_PROPERTY = "throwingName";
    private static final String ARG_NAMES = "arg-names";
    private static final String ARG_NAMES_PROPERTY = "argumentNames";
    private static final String ASPECT_NAME_PROPERTY = "aspectName";
    private static final String DECLARATION_ORDER_PROPERTY = "declarationOrder";
    private static final String ORDER_PROPERTY = "order";
    private static final int METHOD_INDEX = 0;
    private static final int POINTCUT_INDEX = 1;
    private static final int ASPECT_INSTANCE_FACTORY_INDEX = 2;

    private ParseState parseState = new ParseState();

    /**
       <bean id="logBeforeAdvice" class="org.spring.aop.config.LogBeforeAdvice"></bean>
            <aop:config proxy-target-class="true">
            <aop:advisor id="logBeforeAdvisor" advice-ref="logBeforeAdvice" pointcut="execution(* org.spring.aop.service..*.*(..))"></aop:advisor>
        </aop:config>
     注意:<aop:advisor>生成的advisor的BeanDefinition的beanClass类型是:DefaultBeanFactoryPointcutAdvisor,对应构造函数是无参构造函数
          <aop:advisor>属性advice-ref对应的 advice bean 是自定义的,需要实现接口Advice

        <aop:config proxy-target-class="true">
            <aop:aspect ref="aopAdvice">
                <aop:pointcut expression="execution(* org.spring.aop.service..*.*(..))" id="callAt"/>
                <aop:around method="around" pointcut-ref="callAt"/>
                <aop:before method="before" pointcut="execution(* org.spring.aop.service..*.*(..))"/>
            </aop:aspect>
     </aop:config>
     注意:<aop:aspect>生成的advisor的BeanDefinition的beanClass类型是:AspectJPointcutAdvisor,对应构成函数AspectJPointcutAdvisor(AbstractAspectJAdvice advice)
          <aop:aspect>下的每个Advice都有自己的实现
             1、<aop:around>==》AspectJAroundAdvice
             2、<aop:before>==》AspectJMethodBeforeAdvice
             3、<aop:after>==》AspectJAfterAdvice
             4、<aop:after-returning>==》AspectJAfterReturningAdvice
             5、<aop:after-throwing>==》AspectJAfterThrowingAdvice
          上面Advice构造函数初始化时会匹配三参构造函数:AbstractAspectJAdvice(Method aspectJAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aspectInstanceFactory)
          AbstractAspectJAdvice是上面5个Advice的父类


     所有的PointCut生成的BeanDefinition的beanClass类型是:AspectJExpressionPointcut

     解析完成后会将生成的advisor的BeanDefinition注册到IOC容器

     如果pointcut是元素<aop:pointcut>生成的BeanDefinition会注册到IOC容器;
     如果pointcut是属性pointcut="execution(* org.spring.aop.service..*.*(..))"生成的BeanDefinition不会注册到IOC容器;
     */
    @Override
    public BeanDefinition parse(Element element, ParserContext parserContext) {
        CompositeComponentDefinition compositeDef =
                new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
        parserContext.pushContainingComponent(compositeDef);

        /**
         * @see AspectJAwareAdvisorAutoProxyCreator
         * 创建BeanDefinition,对应的beanClass为AspectJAwareAdvisorAutoProxyCreator
         * 实现了后置处理器 SmartInstantiationAwareBeanPostProcessor、InstantiationAwareBeanPostProcessor、BeanPostProcessor
         *
            SmartInstantiationAwareBeanPostProcessor

                //AbstractAutoProxyCreator#predictBeanType
                Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException;

                //AbstractAutoProxyCreator#determineCandidateConstructors  直接返回null
                Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException;

                //AbstractAutoProxyCreator#getEarlyBeanReference
                Object getEarlyBeanReference(Object bean, String beanName) throws BeansException;


            InstantiationAwareBeanPostProcessor

                //负责创建advisor,在每个bean创建前执行,关键入口
                //AbstractAutoProxyCreator#postProcessBeforeInstantiation
                Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException;

                //AbstractAutoProxyCreator#postProcessAfterInstantiation  直接返回true
                boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException;

                //AbstractAutoProxyCreator#postProcessPropertyValues 直接返回pvs
                PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException;


            BeanPostProcessor

                //AbstractAutoProxyCreator#postProcessBeforeInitialization 直接返回bean
                Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;

                //负责创建aop相关工作,将advisor关联到bean,在每个bean创建并初始化完成后执行,关键入口
                //AbstractAutoProxyCreator#postProcessAfterInitialization
                Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
         *
         */
        configureAutoProxyCreator(parserContext, element);

        List<Element> childElts = DomUtils.getChildElements(element);
        for (Element elt: childElts) {
            String localName = parserContext.getDelegate().getLocalName(elt);
            if (POINTCUT.equals(localName)) {
                parsePointcut(elt, parserContext);
            }
            else if (ADVISOR.equals(localName)) {
                parseAdvisor(elt, parserContext);
            }
            else if (ASPECT.equals(localName)) {
                parseAspect(elt, parserContext);
            }
        }

        parserContext.popAndRegisterContainingComponent();
        return null;
    }

    /**
     * 创建BeanDefinition,对应的beanClass为AspectJAwareAdvisorAutoProxyCreator
     * @see AspectJAwareAdvisorAutoProxyCreator
     *
     * 实现了后置处理器 SmartInstantiationAwareBeanPostProcessor--实现-》InstantiationAwareBeanPostProcessor-实现--》BeanPostProcessor
     *
     */
    private void configureAutoProxyCreator(ParserContext parserContext, Element element) {
        AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary(parserContext, element);
    }


    /**
     * 解析元素<aop:pointcut/>
     *
        <aop:config proxy-target-class="true">
            <aop:pointcut id="callAt" expression="execution(* org.spring.aop.service..*.*(..))"></aop:pointcut>
        </aop:config>

     *  创建Pointcut BeanDefinition,beanClass为:AspectJExpressionPointcut
     * @see AspectJExpressionPointcut
     * 设置beanDefinition 属性 expression
     */
    private AbstractBeanDefinition parsePointcut(Element pointcutElement, ParserContext parserContext) {
        String id = pointcutElement.getAttribute(ID);
        String expression = pointcutElement.getAttribute(EXPRESSION);

        AbstractBeanDefinition pointcutDefinition = null;

        try {
            this.parseState.push(new PointcutEntry(id));
            //创建Pointcut BeanDefinition,beanClass为:AspectJExpressionPointcut
            pointcutDefinition = createPointcutDefinition(expression);
            pointcutDefinition.setSource(parserContext.extractSource(pointcutElement));

            //设置Pointcut BeanDefinition的beanName为id,如果id为空,用beanClassName+递增数字
            String pointcutBeanName = id;
            if (StringUtils.hasText(pointcutBeanName)) {
                parserContext.getRegistry().registerBeanDefinition(pointcutBeanName, pointcutDefinition);
            }
            else {
                pointcutBeanName = parserContext.getReaderContext().registerWithGeneratedName(pointcutDefinition);
            }

            parserContext.registerComponent(
                    new PointcutComponentDefinition(pointcutBeanName, pointcutDefinition, expression));
        }
        finally {
            this.parseState.pop();
        }

        return pointcutDefinition;
    }

    /**
     * 解析元素<aop:advisor/>
     *
        <bean id="logBeforeAdvice" class="org.spring.aop.config.LogBeforeAdvice"></bean>
        <aop:config proxy-target-class="true">
            <aop:advisor id="logBeforeAdvisor" advice-ref="logBeforeAdvice" pointcut="execution(* org.spring.aop.service..*.*(..))"></aop:advisor>
        </aop:config>

     *  创建Advisor对应的BeanDefinition,beanClass为:DefaultBeanFactoryPointcutAdvisor
     * @see DefaultBeanFactoryPointcutAdvisor
     * 设置beanDefinition 属性 expression
     */
    private void parseAdvisor(Element advisorElement, ParserContext parserContext) {
        //创建Advisor对应的BeanDefinition,beanClass为:DefaultBeanFactoryPointcutAdvisor
        AbstractBeanDefinition advisorDef = createAdvisorBeanDefinition(advisorElement, parserContext);
        String id = advisorElement.getAttribute(ID);

        try {
            this.parseState.push(new AdvisorEntry(id));
            String advisorBeanName = id;
            if (StringUtils.hasText(advisorBeanName)) {
                parserContext.getRegistry().registerBeanDefinition(advisorBeanName, advisorDef);
            }
            else {
                advisorBeanName = parserContext.getReaderContext().registerWithGeneratedName(advisorDef);
            }

            //设置依赖的Pointcut
            Object pointcut = parsePointcutProperty(advisorElement, parserContext);
            if (pointcut instanceof BeanDefinition) { //pointcut,属性值为BeanDefinition,后续填充属性时,做依赖bean处理
                advisorDef.getPropertyValues().add(POINTCUT, pointcut);
                parserContext.registerComponent(
                        new AdvisorComponentDefinition(advisorBeanName, advisorDef, (BeanDefinition) pointcut));
            }
            else if (pointcut instanceof String) {//pointcut-ref,属性值为RuntimeBeanReference,后续填充属性时,做依赖bean处理
                advisorDef.getPropertyValues().add(POINTCUT, new RuntimeBeanReference((String) pointcut));
                parserContext.registerComponent(
                        new AdvisorComponentDefinition(advisorBeanName, advisorDef));
            }
        }
        finally {
            this.parseState.pop();
        }
    }

    /**
     * 解析元素<aop:aspect/>
     *
        <bean id="aopAdvice" class="org.spring.aop.aspectj.AopAdvice"></bean>

        <aop:config proxy-target-class="true">
            <aop:aspect ref="aopAdvice">
                <aop:pointcut expression="execution(* org.spring.aop.service..*.*(..))" id="callAt"/>
                <aop:around method="around" pointcut-ref="callAt"/>
                <aop:before method="before" pointcut="execution(* org.spring.aop.service..*.*(..))"/>
                <aop:after method="before" pointcut="execution(* org.spring.aop.service..*.*(..))"/>
            </aop:aspect>
        </aop:config>
     *
     *
     *  创建Pointcut BeanDefinition,beanClass为:AspectJExpressionPointcut
     * @see AspectJExpressionPointcut
     * 设置beanDefinition 属性 expression  AspectJPointcutAdvisor
     */
    private void parseAspect(Element aspectElement, ParserContext parserContext) {
        String aspectId = aspectElement.getAttribute(ID);
        String aspectName = aspectElement.getAttribute(REF);

        try {
            this.parseState.push(new AspectEntry(aspectId, aspectName));
            //存储BeanDefinition形式的PointCut
            List<BeanDefinition> beanDefinitions = new ArrayList<>();
            //存储BeanReference形式的PointCut 额外存储了beanReferences.add(new RuntimeBeanReference(aspectName))
            List<BeanReference> beanReferences = new ArrayList<>();


            //解析引介增强方式
            List<Element> declareParents = DomUtils.getChildElementsByTagName(aspectElement, DECLARE_PARENTS);
            for (int i = METHOD_INDEX; i < declareParents.size(); i++) {
                Element declareParentsElement = declareParents.get(i);
                beanDefinitions.add(parseDeclareParents(declareParentsElement, parserContext));
            }


            // We have to parse "advice" and all the advice kinds in one loop, to get the
            // ordering semantics right.


            /*
                循环Advice,生成Advice和Advisor的BeanDefinition
                Advice与Advisor一样对应
             */
            NodeList nodeList = aspectElement.getChildNodes();
            boolean adviceFoundAlready = false;
            for (int i = 0; i < nodeList.getLength(); i++) {
                Node node = nodeList.item(i);
                if (isAdviceNode(node, parserContext)) {
                    if (!adviceFoundAlready) {
                        adviceFoundAlready = true;
                        if (!StringUtils.hasText(aspectName)) {
                            parserContext.getReaderContext().error(
                                    "<aspect> tag needs aspect bean reference via 'ref' attribute when declaring advices.",
                                    aspectElement, this.parseState.snapshot());
                            return;
                        }
                        beanReferences.add(new RuntimeBeanReference(aspectName));
                    }
                    //生成单个Advisor的Definition
                    AbstractBeanDefinition advisorDefinition = parseAdvice(
                            aspectName, i, aspectElement, (Element) node, parserContext, beanDefinitions, beanReferences);
                    beanDefinitions.add(advisorDefinition);
                }
            }

            //注册事件相关的
            AspectComponentDefinition aspectComponentDefinition = createAspectComponentDefinition(
                    aspectElement, aspectId, beanDefinitions, beanReferences, parserContext);
            parserContext.pushContainingComponent(aspectComponentDefinition);

            List<Element> pointcuts = DomUtils.getChildElementsByTagName(aspectElement, POINTCUT);
            for (Element pointcutElement : pointcuts) {
                //解析里面的<aop:pointcut>元素
                parsePointcut(pointcutElement, parserContext);
            }

            //注册事件相关的
            parserContext.popAndRegisterContainingComponent();
        }
        finally {
            this.parseState.pop();
        }
    }

    //注册事件相关的
    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);
    }


    /**
     *  创建Pointcut对应的BeanDefinition,beanClass为:AspectJExpressionPointcut
     * @see AspectJExpressionPointcut
     *
     * 设置beanDefinition 属性 expression
     */
    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;
    }

    /**
     *  创建Advisor对应的BeanDefinition,beanClass为:DefaultBeanFactoryPointcutAdvisor
     * @see DefaultBeanFactoryPointcutAdvisor
     *
     * 设置beanDefinition 属性 expression
     */
    private AbstractBeanDefinition createAdvisorBeanDefinition(Element advisorElement, ParserContext parserContext) {
        RootBeanDefinition advisorDefinition = new RootBeanDefinition(DefaultBeanFactoryPointcutAdvisor.class);
        advisorDefinition.setSource(parserContext.extractSource(advisorElement));

        String adviceRef = advisorElement.getAttribute(ADVICE_REF);
        if (!StringUtils.hasText(adviceRef)) {
            parserContext.getReaderContext().error(
                    "'advice-ref' attribute contains empty value.", advisorElement, this.parseState.snapshot());
        }
        else { //设置依赖的Advice
            advisorDefinition.getPropertyValues().add(
                    ADVICE_BEAN_NAME, new RuntimeBeanNameReference(adviceRef));
        }

        if (advisorElement.hasAttribute(ORDER_PROPERTY)) {
            advisorDefinition.getPropertyValues().add(
                    ORDER_PROPERTY, advisorElement.getAttribute(ORDER_PROPERTY));
        }

        return advisorDefinition;
    }

    /**
     * 解析pointcut或者pointcut-ref,属性不能同时出现,二者选一
     *  pointcut="execution(* org.spring.aop.service..*.*(..))"
     *  pointcut-ref="callAt"
     *
     * @return
     */
    private Object parsePointcutProperty(Element element, ParserContext parserContext) {
        if (element.hasAttribute(POINTCUT) && element.hasAttribute(POINTCUT_REF)) {
            parserContext.getReaderContext().error(
                    "Cannot define both 'pointcut' and 'pointcut-ref' on <advisor> tag.",
                    element, this.parseState.snapshot());
            return null;
        }
        else if (element.hasAttribute(POINTCUT)) { //为pointcut时,创建BeanDefinition,beanClass为:AspectJExpressionPointcut
            String expression = element.getAttribute(POINTCUT);
            AbstractBeanDefinition pointcutDefinition = createPointcutDefinition(expression);
            pointcutDefinition.setSource(parserContext.extractSource(element));
            return pointcutDefinition;
        }
        else if (element.hasAttribute(POINTCUT_REF)) { //为pointcut-ref时,直接返回字符串内容
            String pointcutRef = element.getAttribute(POINTCUT_REF);
            if (!StringUtils.hasText(pointcutRef)) {
                parserContext.getReaderContext().error(
                        "'pointcut-ref' attribute contains empty value.", element, this.parseState.snapshot());
                return null;
            }
            return pointcutRef;
        }
        else {
            parserContext.getReaderContext().error(
                    "Must define one of 'pointcut' or 'pointcut-ref' on <advisor> tag.",
                    element, this.parseState.snapshot());
            return null;
        }
    }

    /*
        1、创建PointCut的BeanDefinition,PointCut代表拦截点
        2、创建Advice的BeanDefinition,Advice代表在哪个位置增强,around、before、after、return、throw
        3、创建Advisor的BeanDefinition,持有Advice的BeanDefinition
     */
    //beanDefinitions, BeanDefinition形式的PointCut
    //beanReferences, BeanReference形式的PointCut
    private AbstractBeanDefinition parseAdvice(
            String aspectName, int order, Element aspectElement, Element adviceElement, ParserContext parserContext,
            List<BeanDefinition> beanDefinitions, List<BeanReference> beanReferences) {

        try {
            this.parseState.push(new AdviceEntry(parserContext.getDelegate().getLocalName(adviceElement)));

            /*
            <bean id="aopAdvice" class="org.spring.aop.aspectj.AopAdvice"></bean>
            <aop:config proxy-target-class="true">
                <aop:aspect ref="aopAdvice">
                    <aop:around method="around" pointcut-ref="execution(* org.spring.aop.service..*.*(..))"/>
                </aop:aspect>
            </aop:config>
             */
            //MethodLocatingFactoryBean主要用途是根据类名(targetBeanName)和方法名(methodName)获取Advice实例的method方法对象 AopAdvice.around()
            RootBeanDefinition methodDefinition = new RootBeanDefinition(MethodLocatingFactoryBean.class);
            methodDefinition.getPropertyValues().add("targetBeanName", aspectName);
            methodDefinition.getPropertyValues().add("methodName", adviceElement.getAttribute("method"));
            methodDefinition.setSynthetic(true);

            //SimpleBeanFactoryAwareAspectInstanceFactory用途主要是根据aspectBeanName获取Advice的Bean实例
            //<bean id="aopAdvice" class="org.spring.aop.aspectj.AopAdvice"></bean>
            //将来可以查询bean==》aopAdvice
            RootBeanDefinition aspectFactoryDef =
                    new RootBeanDefinition(SimpleBeanFactoryAwareAspectInstanceFactory.class);
            aspectFactoryDef.getPropertyValues().add("aspectBeanName", aspectName);
            aspectFactoryDef.setSynthetic(true);

            // 创建Advice的BeanDefinition
            //AspectJAroundAdvice构造方法==>public AspectJAroundAdvice(Method aspectJAroundAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {}
            //下面代码构建上述构造函数的BeanDefinition
            AbstractBeanDefinition adviceDef = createAdviceDefinition(
                    adviceElement, parserContext, aspectName, order, methodDefinition, aspectFactoryDef,
                    beanDefinitions, beanReferences);

            // 创建Advisor的BeanDefinition, 构造函数参数是上面Advice的BeanDefinition
            RootBeanDefinition advisorDefinition = new RootBeanDefinition(AspectJPointcutAdvisor.class);
            advisorDefinition.setSource(parserContext.extractSource(adviceElement));
            advisorDefinition.getConstructorArgumentValues().addGenericArgumentValue(adviceDef);
            if (aspectElement.hasAttribute(ORDER_PROPERTY)) {
                advisorDefinition.getPropertyValues().add(
                        ORDER_PROPERTY, aspectElement.getAttribute(ORDER_PROPERTY));
            }

            // 将advisor的BeanDefinition注册进IOC容器
            parserContext.getReaderContext().registerWithGeneratedName(advisorDefinition);

            return advisorDefinition;
        }
        finally {
            this.parseState.pop();
        }
    }

    /*
        创建advice对应的BeanDefinition,
            BeanDefinition的beanClass由advice元素名称决定
                1、<aop:around>==》AspectJAroundAdvice
                2、<aop:before>==》AspectJMethodBeforeAdvice
                3、<aop:after>==》AspectJAfterAdvice
                4、<aop:after-returning>==》AspectJAfterReturningAdvice
                5、<aop:after-throwing>==》AspectJAfterThrowingAdvice
           BeanDefinition有三个构造函数参数
               第一个参数:methodDef ==> RootBeanDefinition(MethodLocatingFactoryBean.class)
                       有两个属性:targetBeanName对应<aop:aspect ref="aopAdvice">的ref值
                                 methodName对应<aop:around method="around">的method值
               第二个参数:pointcut
                            <aop:around pointcut-ref="callAt"/>类型就是RuntimeBeanReference(expression),其实最后还是AspectJExpressionPointcut
                            <aop:before pointcut="execution(* xxx.xxx.service..*.*(..))"/>类型就是RootBeanDefinition(AspectJExpressionPointcut)
               第三个参数:aspectFactoryDef ==> RootBeanDefinition(SimpleBeanFactoryAwareAspectInstanceFactory.class)
                        有个一个属性:aspectBeanName对应<aop:aspect ref="aopAdvice">的ref值

         比如环绕advice: AspectJAroundAdvice
         构造方法==>public AspectJAroundAdvice(Method aspectJAroundAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {}
    */
    //beanDefinitions, BeanDefinition形式的PointCut,后面直接注册进IOC容器
    //beanReferences, BeanReference形式的PointCut,后面封装成BeanDefinition注册进IOC容器
    private AbstractBeanDefinition createAdviceDefinition(
            Element adviceElement, ParserContext parserContext, String aspectName, int order,
            RootBeanDefinition methodDef, RootBeanDefinition aspectFactoryDef,
            List<BeanDefinition> beanDefinitions, List<BeanReference> beanReferences) {

        RootBeanDefinition adviceDefinition = new RootBeanDefinition(getAdviceClass(adviceElement, parserContext));
        adviceDefinition.setSource(parserContext.extractSource(adviceElement));

        adviceDefinition.getPropertyValues().add(ASPECT_NAME_PROPERTY, aspectName);
        adviceDefinition.getPropertyValues().add(DECLARATION_ORDER_PROPERTY, order);

        if (adviceElement.hasAttribute(RETURNING)) {
            adviceDefinition.getPropertyValues().add(
                    RETURNING_PROPERTY, adviceElement.getAttribute(RETURNING));
        }
        if (adviceElement.hasAttribute(THROWING)) {
            adviceDefinition.getPropertyValues().add(
                    THROWING_PROPERTY, adviceElement.getAttribute(THROWING));
        }
        if (adviceElement.hasAttribute(ARG_NAMES)) {
            adviceDefinition.getPropertyValues().add(
                    ARG_NAMES_PROPERTY, adviceElement.getAttribute(ARG_NAMES));
        }

        //创建adviceDefinition的构造函数
        ConstructorArgumentValues cav = adviceDefinition.getConstructorArgumentValues();
        cav.addIndexedArgumentValue(METHOD_INDEX, methodDef);

        /**
         * 解析pointcut或者pointcut-ref,属性不能同时出现,二者选一
         *  pointcut="execution(* org.spring.aop.service..*.*(..))"
         *  pointcut-ref="callAt"
         */
        Object pointcut = parsePointcutProperty(adviceElement, parserContext);
        if (pointcut instanceof BeanDefinition) {
            cav.addIndexedArgumentValue(POINTCUT_INDEX, pointcut);
            beanDefinitions.add((BeanDefinition) pointcut);
        }
        else if (pointcut instanceof String) {
            RuntimeBeanReference pointcutRef = new RuntimeBeanReference((String) pointcut);
            cav.addIndexedArgumentValue(POINTCUT_INDEX, pointcutRef);
            beanReferences.add(pointcutRef);
        }

        cav.addIndexedArgumentValue(ASPECT_INSTANCE_FACTORY_INDEX, aspectFactoryDef);

        return adviceDefinition;
    }

    /*
     * 根据advice元素名称获取对应的beanClass
     *  <aop:around>==》AspectJAroundAdvice
     *  <aop:before>==》AspectJMethodBeforeAdvice
     *  <aop:after>==》AspectJAfterAdvice
     *  <aop:after-returning>==》AspectJAfterReturningAdvice
     *  <aop:after-throwing>==》AspectJAfterThrowingAdvice
     *
     */
    private Class getAdviceClass(Element adviceElement, ParserContext parserContext) {
        String elementName = parserContext.getDelegate().getLocalName(adviceElement);
        if (BEFORE.equals(elementName)) {
            return AspectJMethodBeforeAdvice.class;
        }
        else if (AFTER.equals(elementName)) {
            return AspectJAfterAdvice.class;
        }
        else if (AFTER_RETURNING_ELEMENT.equals(elementName)) {
            return AspectJAfterReturningAdvice.class;
        }
        else if (AFTER_THROWING_ELEMENT.equals(elementName)) {
            return AspectJAfterThrowingAdvice.class;
        }
        else if (AROUND.equals(elementName)) {
            return AspectJAroundAdvice.class;
        }
        else {
            throw new IllegalArgumentException("Unknown advice kind [" + elementName + "].");
        }
    }


    /**
     * 判断是否为advice节点元素
     */
    private boolean isAdviceNode(Node aNode, ParserContext parserContext) {
        if (!(aNode instanceof Element)) {
            return false;
        }
        else {
            String name = parserContext.getDelegate().getLocalName(aNode);
            return (BEFORE.equals(name) || AFTER.equals(name) || AFTER_RETURNING_ELEMENT.equals(name) ||
                    AFTER_THROWING_ELEMENT.equals(name) || AROUND.equals(name));
        }
    }


    /**
     *  解析引介增强方式 	<aop:declare-parents types-matching="匹配要被引介增强的类" implement-interface="引介增强接口" default-impl="引介增强实现类"/>
     * @return
     */
    private AbstractBeanDefinition parseDeclareParents(Element declareParentsElement, ParserContext parserContext) {
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(DeclareParentsAdvisor.class);
        //引介增强接口
        builder.addConstructorArgValue(declareParentsElement.getAttribute(IMPLEMENT_INTERFACE));
        //匹配要被引介增强的类
        builder.addConstructorArgValue(declareParentsElement.getAttribute(TYPE_PATTERN));

        //引介增强实现类全路径
        String defaultImpl = declareParentsElement.getAttribute(DEFAULT_IMPL);
        //引介增强实现类bean对象
        String delegateRef = declareParentsElement.getAttribute(DELEGATE_REF);

        if (StringUtils.hasText(defaultImpl) && !StringUtils.hasText(delegateRef)) {
            builder.addConstructorArgValue(defaultImpl);
        }
        else if (StringUtils.hasText(delegateRef) && !StringUtils.hasText(defaultImpl)) {
            builder.addConstructorArgReference(delegateRef);
        }
        else {
            parserContext.getReaderContext().error(
                    "Exactly one of the " + DEFAULT_IMPL + " or " + DELEGATE_REF + " attributes must be specified",
                    declareParentsElement, this.parseState.snapshot());
        }

        AbstractBeanDefinition definition = builder.getBeanDefinition();
        definition.setSource(parserContext.extractSource(declareParentsElement));
        parserContext.getReaderContext().registerWithGeneratedName(definition);
        return definition;
    }
}
AspectJAwareAdvisorAutoProxyCreator:ConfigBeanDefinitionParser中会创建AspectJAwareAdvisorAutoProxyCreator的BeanDefinition,在ApplicationContext的refresh()中自动调用,将AspectJAwareAdvisorAutoProxyCreator转为对象。

AspectJAwareAdvisorAutoProxyCreator实现了接口BeanPostProcessor,说明它是个后置处理器,所以每个bean初始化完成后会执行BeanPostProcessor.postProcessAfterInitialization(Object bean, String beanName),对应实现在父类AbstractAutoProxyCreator
package org.springframework.aop.framework.autoproxy;

public abstract class AbstractAutoProxyCreator extends ProxyConfig
		implements SmartInstantiationAwareBeanPostProcessor, BeanClassLoaderAware, BeanFactoryAware,
		Ordered, AopInfrastructureBean {

	// ...其它代码代码(略)

	//源码分析:节点1
	//关键入口
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		if (bean != null) {
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			if (!this.earlyProxyReferences.containsKey(cacheKey)) {
				//源码分析:节点2
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}

	//源码分析:节点2
	protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		if (beanName != null && this.targetSourcedBeans.containsKey(beanName)) {
			return bean;
		}
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}

		//源码分析:节点3
		// 将当前容器中的所以Advisor和当前bean匹配,最后将匹配成功的Advisor列表返回
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		if (specificInterceptors != DO_NOT_PROXY) {
			this.advisedBeans.put(cacheKey, Boolean.TRUE);

			//源码分析:节点4
			//创建代理对象
			Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}

	//源码分析:节点4
	//创建代理对象
	//参考CSDN博文:https://blog.csdn.net/java_key_code/article/details/140076947
	protected Object createProxy(
			Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {

		ProxyFactory proxyFactory = new ProxyFactory();
		// Copy our properties (proxyTargetClass etc) inherited from ProxyConfig.
		proxyFactory.copyFrom(this);

		if (!shouldProxyTargetClass(beanClass, beanName)) {
			// Must allow for introductions; can't just set interfaces to
			// the target's interfaces only.
			Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, this.proxyClassLoader);
			for (Class<?> targetInterface : targetInterfaces) {
				proxyFactory.addInterface(targetInterface);
			}
		}

		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		for (Advisor advisor : advisors) {
			proxyFactory.addAdvisor(advisor);
		}

		proxyFactory.setTargetSource(targetSource);
		customizeProxyFactory(proxyFactory);

		proxyFactory.setFrozen(this.freezeProxy);
		if (advisorsPreFiltered()) {
			proxyFactory.setPreFiltered(true);
		}

		return proxyFactory.getProxy(this.proxyClassLoader);
	}

    // ...其它代码代码(略)
}
源码分析:节点3
package org.springframework.aop.framework.autoproxy;

import java.util.List;

import org.springframework.aop.Advisor;
import org.springframework.aop.TargetSource;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.core.OrderComparator;

public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator {

    // ...其它代码代码(略)

    //源码分析:节点3
    @Override
    protected Object[] getAdvicesAndAdvisorsForBean(Class beanClass, String beanName, TargetSource targetSource) {
        //源码分析:节点3 分支1
        List advisors = findEligibleAdvisors(beanClass, beanName);
        if (advisors.isEmpty()) {
            return DO_NOT_PROXY;
        }
        return advisors.toArray();
    }

    //源码分析:节点3 分支1
    protected List<Advisor> findEligibleAdvisors(Class beanClass, String beanName) {
        //获取所有的候选Advisor
        List<Advisor> candidateAdvisors = findCandidateAdvisors();
        //和当前bean匹配,获取匹配成功的Advisor
        List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
        //额外添加一个Advisor:ExposeInvocationInterceptor.ADVISOR
        //将MethodInvocation放到ThreadLocal,这个类很重要
        /**
         public class ExposeInvocationInterceptor implements MethodInterceptor, Ordered, Serializable {

             private static final ThreadLocal<MethodInvocation> invocation = new NamedThreadLocal<MethodInvocation>("Current AOP method invocation");
    
             public Object invoke(MethodInvocation mi) throws Throwable {
                MethodInvocation oldInvocation = invocation.get();
                invocation.set(mi);
                try {
                    return mi.proceed();
                }
                finally {
                    invocation.set(oldInvocation);
                }
             }
         }
         */
        extendAdvisors(eligibleAdvisors);
        if (!eligibleAdvisors.isEmpty()) {
            eligibleAdvisors = sortAdvisors(eligibleAdvisors);
        }
        return eligibleAdvisors;
    }

    protected List<Advisor> findCandidateAdvisors() {
        return this.advisorRetrievalHelper.findAdvisorBeans();
    }

    protected List<Advisor> findAdvisorsThatCanApply(
            List<Advisor> candidateAdvisors, Class beanClass, String beanName) {

        ProxyCreationContext.setCurrentProxiedBeanName(beanName);
        try {
            return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
        }
        finally {
            ProxyCreationContext.setCurrentProxiedBeanName(null);
        }
    }

    // ...其它代码代码(略)
}

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值