美文网首页
Spring4 Aop标签解析源码

Spring4 Aop标签解析源码

作者: sunpy | 来源:发表于2019-03-20 22:41 被阅读0次

例子

<bean id="myAop" class="cn.spy.spring.test.MyAop"></bean>
<bean id="myService" class="cn.spy.spring.test.MyService"></bean>
    
<aop:config>
   <aop:pointcut id="myPointCut" expression="execution(* cn.spy.spring.test.MyService.*(..))"/>
   <aop:aspect ref="myAop">
       <aop:before method="beforeExecute" pointcut-ref="myPointCut"/>
       <aop:after method="afterExecute" pointcut-ref="myPointCut"/>
   </aop:aspect>
</aop:config>
public class MyAop {
    
    public void beforeExecute() {
        System.out.println("beforeExecute");
    }
    
    public void afterExecute() {
        System.out.println("afterExecute");
    }
}

public class MyService {
    
    public void execute() {
        System.out.println("MyService execute");
    }
}
public static void main(String[] args) {
    ApplicationContext ac = new ClassPathXmlApplicationContext(new String[]{"spring.xml"});
    MyService myService = ac.getBean("myService", MyService.class);
    myService.execute();
}

##结果
beforeExecute
MyService execute
afterExecute

源码解析

从IOC的xml配置解析的位置开始:
DefaultBeanDefinitionDocumentReader类之parseBeanDefinitions

// 解析文档中的根级别元素(import标签,alias标签,bean标签,beans元素)
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
    // Bean定义的document对象使用spring的默认xml命名空间
    if (delegate.isDefaultNamespace(root)) {
        // 获取bean根元素下的所有子节点
        NodeList nl = root.getChildNodes();
        // 遍历所有子节点
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            // 判断节点是否为Element元素节点
            if (node instanceof Element) {
                // 将节点node强制类型转为Element元素
                Element ele = (Element) node;
                // 使用Spring的Bean规则解析元素节点
                if (delegate.isDefaultNamespace(ele)) {
                    parseDefaultElement(ele, delegate);
                }
                else {// 使用用户自定义的命名空间解析
                    delegate.parseCustomElement(ele);
                }
            }
        }
    }
    else {
        // 根节点没有使用spring的默认命名空间,就使用用户自定义的命名空间解析
        delegate.parseCustomElement(root);
    }
}

说明:
parseDefaultElement方法主要解析的元素是<import>,<alias>,<bean>,<beans>元素等。
parseCustomElement方法主要解析自定义元素。而<aop:config>元素的解析就是在parseCustomElement方法中。


BeanDefinitionParserDelegate类之parseCustomElement方法,解析自定义元素

public BeanDefinition parseCustomElement(Element ele) {
    return parseCustomElement(ele, null);
}

public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
    // 获取命名空间Uri
    String namespaceUri = getNamespaceURI(ele);
    // 通过命名空间Uri获取对应的AopNamespaceHandler(Aop命名空间解析器)
    NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
    // 如果不存在对应的解析器,那么直接返回
    if (handler == null) {
        error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
        return null;
    }
    // 委派给BeanDefinitionParser解析已经注册的Element
    return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}

NamespaceHandlerSupport类之findParserForElement方法,使用Element的localName查找相应的BeanDefinitionParser (BeanDefinition解析器)

// 委派给BeanDefinitionParser解析已经注册的Element
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
    return findParserForElement(element, parserContext).parse(element, parserContext);
}

// 使用Element查找对应的BeanDefinitionParser
private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {
    // 获取元素节点的本地名称
    String localName = parserContext.getDelegate().getLocalName(element);
    // 通过本地名称获取对应的BeanDefinitionParser(BeanDefinition解析器)
    BeanDefinitionParser parser = this.parsers.get(localName);
    if (parser == null) {
        parserContext.getReaderContext().fatal(
                "Cannot locate BeanDefinitionParser for element [" + localName + "]", element);
    }
    return parser;
}

ConfigBeanDefinitionParser类之parse方法,解析Element元素转换为BeanDefinition

// 通过element元素解析出BeanDefinition
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
    CompositeComponentDefinition compositeDef =
            new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
    parserContext.pushContainingComponent(compositeDef);
    // 配置创建的代理
    // 创建BeanDefinition所需要的代理类
    configureAutoProxyCreator(parserContext, element);
    // 获取元素的所有子元素
    List<Element> childElts = DomUtils.getChildElements(element);
    // 遍历所有子元素
    for (Element elt: childElts) {
        // 获取元素的本地名称
        String localName = parserContext.getDelegate().getLocalName(elt);
        
        if (POINTCUT.equals(localName)) {
            // 解析pointcut元素
            parsePointcut(elt, parserContext);
        }
        else if (ADVISOR.equals(localName)) {
            // 解析advisor元素
            parseAdvisor(elt, parserContext);
        }
        else if (ASPECT.equals(localName)) {
            // 解析ASPECT元素
            parseAspect(elt, parserContext);
        }
    }
    parserContext.popAndRegisterContainingComponent();
    return null;
}

// 创建BeanDefinition所需要的代理类
private void configureAutoProxyCreator(ParserContext parserContext, Element element) {
    AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary(parserContext, element);
}

AopNamespaceUtils类之registerAspectJAutoProxyCreatorIfNecessary方法

public static void registerAspectJAutoProxyCreatorIfNecessary(
        ParserContext parserContext, Element sourceElement) {
    // 注册AutoProxyCreator定义beanName为BeanDefinition
    BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAutoProxyCreatorIfNecessary(
            parserContext.getRegistry(), parserContext.extractSource(sourceElement));
    // 处理proxy-target-class和expose-proxy属性
    useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
    // 注册组件,并且通知监听器
    registerComponentIfNecessary(beanDefinition, parserContext);
}

说明:

  1. registerAspectJAutoProxyCreatorIfNecessary方法:注册或者升级AnnotationAwareAspectJAutoProxyCreator。
  2. useClassProxyingIfNecessary方法:处理proxy-target-class以及expose-proxy属性。
  3. registerComponentIfNecessary方法:注册组件并且通知监听器。

AopConfigUtils类之registerAspectJAutoProxyCreatorIfNecessary方法,注册或者升级AnnotationAwareAspectJAutoProxyCreator

public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
    return registerOrEscalateApcAsRequired(AspectJAwareAdvisorAutoProxyCreator.class, registry, source);
}

private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    // public static final String AUTO_PROXY_CREATOR_BEAN_NAME = "org.springframework.aop.config.internalAutoProxyCreator";
    // 判断BeanDefinition注册集合是否包含internalAutoProxyCreator(自动代理创建器)
    if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
        // 从注册集合中获取AUTO_PROXY_CREATOR_BEAN_NAME的Bean名称对应的BeanDefinition
        BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
        // AspectJAwareAdvisorAutoProxyCreator的名称不等于Bean的Class名称
        if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
            // 获取当前Bean的Class名称对应的优先级
            int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
            // 获取AspectJAwareAdvisorAutoProxyCreator需要的优先级
            int requiredPriority = findPriorityForClass(cls);
            // 如果当前的internalAutoProxyCreator比需要的AspectJAwareAdvisorAutoProxyCreator优先级低
            if (currentPriority < requiredPriority) {
                // 设置AspectJAwareAdvisorAutoProxyCreator为BeanDefinition的class名称
                apcDefinition.setBeanClassName(cls.getName());
            }
        }
        return null;
    }
    // 使用AspectJAwareAdvisorAutoProxyCreator创建BeanDefinition
    RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
    beanDefinition.setSource(source);
    // 设置切面优先级
    beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
    beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    // 向ioc容器注册BeanDefinition
    registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
    return beanDefinition;
}

AopNamespaceUtils类之useClassProxyingIfNecessary方法,处理proxy-target-class和expose-proxy属性

// 处理proxy-target-class和expose-proxy属性
private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, Element sourceElement) {
    if (sourceElement != null) {
        // 解析sourceElement元素中的属性proxy-target-class
        boolean proxyTargetClass = Boolean.valueOf(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
        // proxy-target-class属性设置为true
        if (proxyTargetClass) {
            // 使用internalAutoProxyCreator这个beanName在注册集合BeanDefinitionRegistry中找到对应的BeanDefinition
            // 将属性名称proxyTargetClass和值True设置到BeanDefinition
            AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
        }
        // 解析sourceElement元素中的属性expose-proxy
        boolean exposeProxy = Boolean.valueOf(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
        // expose-proxy属性设置为true
        if (exposeProxy) {
            // 使用internalAutoProxyCreator这个beanName在注册集合BeanDefinitionRegistry中找到对应的BeanDefinition
            // 将属性名称exposeProxy和值True设置到BeanDefinition
            AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
        }
    }
}

------------开始解析标签 ----------


ConfigBeanDefinitionParser类之parseAspect方法,解析<aop:aspect>标签

private void parseAspect(Element aspectElement, ParserContext parserContext) {
    // <aop:aspect>
    // 获取aspect的id属性值
    String aspectId = aspectElement.getAttribute(ID);
    // 获取aspect的ref属性值
    String aspectName = aspectElement.getAttribute(REF);

    try {
        this.parseState.push(new AspectEntry(aspectId, aspectName));
        List<BeanDefinition> beanDefinitions = new ArrayList<BeanDefinition>();
        List<BeanReference> beanReferences = new ArrayList<BeanReference>();
        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.
        NodeList nodeList = aspectElement.getChildNodes();
        boolean adviceFoundAlready = false;
        // 遍历节点<aop:aspect>标签的子标签
        for (int i = 0; i < nodeList.getLength(); i++) {
            // 获取当前节点标签
            Node node = nodeList.item(i);
            // 判断当前节点标签是否为<aop:before>、<aop:after>、<aop:after-returning>、<aop:after-throwing method="">、<aop:around method="">
            if (isAdviceNode(node, parserContext)) {
                if (!adviceFoundAlready) {
                    adviceFoundAlready = true;
                    // 如果aspectName是否为实际的文本
                    if (!StringUtils.hasText(aspectName)) {
                        parserContext.getReaderContext().error(
                                "<aspect> tag needs aspect bean reference via 'ref' attribute when declaring advices.",
                                aspectElement, this.parseState.snapshot());
                        return;
                    }
                    // 将切面名称添加到bean引用集合中
                    beanReferences.add(new RuntimeBeanReference(aspectName));
                }
                // 解析通知Advice
                AbstractBeanDefinition advisorDefinition = parseAdvice(
                        aspectName, i, aspectElement, (Element) node, parserContext, beanDefinitions, beanReferences);
                // 将切面AdviceDefinition添加集合中
                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();
    }
}

parseAdvice方法,解析通知Advice

// 解析通知advice
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)));

        // create the method factory bean
        // 创建工厂方法BeanDefinition
        RootBeanDefinition methodDefinition = new RootBeanDefinition(MethodLocatingFactoryBean.class);
        methodDefinition.getPropertyValues().add("targetBeanName", aspectName);
        methodDefinition.getPropertyValues().add("methodName", adviceElement.getAttribute("method"));
        methodDefinition.setSynthetic(true);

        // 创建实例工厂定义
        RootBeanDefinition aspectFactoryDef =
                new RootBeanDefinition(SimpleBeanFactoryAwareAspectInstanceFactory.class);
        aspectFactoryDef.getPropertyValues().add("aspectBeanName", aspectName);
        aspectFactoryDef.setSynthetic(true);

        // 注册切点
        AbstractBeanDefinition adviceDef = createAdviceDefinition(
                adviceElement, parserContext, aspectName, order, methodDefinition, aspectFactoryDef,
                beanDefinitions, beanReferences);

        // 配置通知advice
        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));
        }

        // 将advisorDefinition注册到DefaultListableBeanFactory
        parserContext.getReaderContext().registerWithGeneratedName(advisorDefinition);

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

createAdviceDefinition方法,创建通知BeanDefinition

// 创建AdviceDefinition(BeanDefinition)
private AbstractBeanDefinition createAdviceDefinition(
        Element adviceElement, ParserContext parserContext, String aspectName, int order,
        RootBeanDefinition methodDef, RootBeanDefinition aspectFactoryDef,
        List<BeanDefinition> beanDefinitions, List<BeanReference> beanReferences) {
    // 首先获取通知相关需要的类,然后初始化通知的bean实例
    // AspectJMethodBeforeAdvice(before)、AspectJAfterAdvice(after)、AspectJAfterReturningAdvice(after-returning)
    // AspectJAfterThrowingAdvice(after-throwing)、AspectJAroundAdvice(around)
    RootBeanDefinition adviceDefinition = new RootBeanDefinition(getAdviceClass(adviceElement, parserContext));
    adviceDefinition.setSource(parserContext.extractSource(adviceElement));
    // 设置aspectName属性
    adviceDefinition.getPropertyValues().add(ASPECT_NAME_PROPERTY, aspectName);
    // 设置declarationOrder属性
    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));
    }

    ConstructorArgumentValues cav = adviceDefinition.getConstructorArgumentValues();
    cav.addIndexedArgumentValue(METHOD_INDEX, methodDef);
    // 解析切点标签
    Object pointcut = parsePointcutProperty(adviceElement, parserContext);
    // 如果切点是某个BeanDefinition,那么就添加该切点,关联起来
    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;
}

总结

绕了一圈的目得就是使用Dom去读取XML,然后解析切面aspect标签、切点point-cut标签,放到adviceDefinition(BeanDefinition),最终注册到DefaultListableBeanFactory。

相关文章

网友评论

      本文标题:Spring4 Aop标签解析源码

      本文链接:https://www.haomeiwen.com/subject/johzpqtx.html