aop源码解析一:注册BPP

来源:互联网 发布:nemo软件好用吗 编辑:程序博客网 时间:2024/06/08 02:06

如题,标签<aop:aspectj-autoproxy proxy-target-class="true" expose-proxy="true"/>注册BPP(AspectJAutoProxyBeanDefinitionParser)源码分析

并没有介绍过BPP相关内容 这里简单的讲解下 读者心里有个概念就行 等有时间补写Bean的加载与读取的时候 会好好介绍这个重要的类!
首先 spring在一些特殊的位置插入了一些处理代码(可能有些读者觉得这句话很 不太好理解 我换种表达方式:从加载配置文件到转换成对应的定义类 比如BeanDefinition 再到获取bean 这一整个过程都是spring在做的 他当然能够在任意想插的位置插入代码了) 例如在实例化前后 或者在初始化前后调的方法 这些类一般是BeanPostProcessor的子类 简称BPP

正文

对于aop这样的非标准或者称为自定义命名空间的元素 spring会从spring.handlersspring.handlers文件中的对应关系找到相应的处理类 然后通过init()方法注册一些处理器 aop命名空间的处理类是AopNamespaceHandler 我们看一下他的init()方法

public void init() {    // In 2.0 XSD as well as in 2.1 XSD.    registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());    //    registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());    registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());    // Only in 2.0 XSD: moved to context namespace as of 2.1    registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());}

从上面注册的处理器的关系我们知道 <aop:aspectj-autoproxy>标签的处理器是AspectJAutoProxyBeanDefinitionParser 同样 这是一个继承于BeanDefinitionParser的标准的解析器 我们看一下他的parse()方法

public BeanDefinition parse(Element element, ParserContext parserContext) {    //注册BPP(AnnotationAwareAspectJAutoProxyCreator)    AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);    // 如果有子元素的话 设置属性    extendBeanDefinition(element, parserContext);    return null;}

parse()方法可以说主要做了一件事情就是注册了一个BPP(BeanPostProcessor) 供后续使用

有些人看到这里可能就蒙圈了 这什么东西 名字这么长 看到后面的时候又会说这是什么东西 类的名字这么长 然后就会觉得好难 主要是读者阅读代码不多的原因 如果阅读的多了 你就会形成一个感觉:不管这个类名字多奇怪 名字多长 不过是一些基本类型(map list等)的包装而已 为了完成某一个功能所做的封装而已

//spring中的方法一般都比较清晰 短短的几行代码告诉了你这个方法要做什么事情public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(        ParserContext parserContext, Element sourceElement) {    //注册BPP(AnnotationAwareAspectJAutoProxyCreator)    BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(            parserContext.getRegistry(), parserContext.extractSource(sourceElement));    //根据xml配置 设置AnnotationAwareAspectJAutoProxyCreator的proxyTargetClass exposeProxy属性    useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);    //注册组件bean 并暴露给外部    registerComponentIfNecessary(beanDefinition, parserContext);}

不断的追踪registerAspectJAnnotationAutoProxyCreatorIfNecessary()方法发现 就是注册了个BPP(AspectJAutoProxyBeanDefinitionParser) 不再贴出相关代码 我们看下useClassProxyingIfNecessary()方法

    //处理proxy-target-class 以及 expose-proxy属性    private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, Element sourceElement) {    if (sourceElement != null) {        //proxy-target-class true:强制使用CGLIB代理 推荐使用        boolean proxyTargetClass = Boolean.valueOf(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));        if (proxyTargetClass) {            AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);        }        //expose-proxy true:暴露代理类 解决某些情况下 代理无法完成的情况        boolean exposeProxy = Boolean.valueOf(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));        if (exposeProxy) {            AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);        }    }}

总结

似乎<aop:aspectj-autoproxy>标签做的事情并不多 只是注册了一个BPP 但是这个BPP确实非常重要的! 我们用到的切面编程就依靠这个BPP去驱动实现 后面的文章会介绍这个BPP的源码是怎么实现AOP的

原创粉丝点击