spring源码分析之spring注解@Aspect是如何工作的?

匿名 (未验证) 提交于 2019-12-02 23:38:02

AOP(Aspect Orient Programming),面向切面编程,是面向对象编程OOP的一种补充。面向对象编程是从静态角度考虑程序的结构,面向切面编程是从动态的角度考虑程序运行过程。

AOP底层,就是采用动态代理模式实现的。采用两种代理:JDK的动态代理,与CGLIB的动态代理。JDK的动态代理是面向接口的,CGLIB既可以实现有接口的,又可以实现没有接口的。(对动态代理不了解的可以看看我的其关于动态代理的介绍)

面向切面编程,就是将交叉业务逻辑封装成切面,利用AOP容器的功能将切面植入到主业务逻辑中。所谓交叉业务逻辑是指:通用的,与主业务逻辑无关的代码,如安全检查,事务日志等。

@Aspect可以使用切点函数定义切点,我们还可以使用逻辑运算符对切点进行复核运算得到复合的切点,为了在切面中重用切点,我们还可以对切点进行命名,以便在其他的地方引用定义过的切点。当一个连接点匹配多个切点时,需要考虑织入顺序的问题,此外一个重要的问题是如何再增强中访问连接点上下文的信息。

1、@Aspect

在xml定义:<aop:aspectj-autoproxy />,
其定义在http://www.springframework.org/schema/aop/spring-aop-3.0.xsd

- <xsd:element name="aspectj-autoproxy"> - <xsd:annotation> - <xsd:documentation source="java:org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"> - <![CDATA[      Enables the use of the @AspectJ style of Spring AOP.    ]]>    </xsd:documentation>   </xsd:annotation> - <xsd:complexType> - <xsd:sequence> - <xsd:element name="include" type="includeType" minOccurs="0" maxOccurs="unbounded"> - <xsd:annotation> - <xsd:documentation> - <![CDATA[      Indicates that only @AspectJ beans with names matched by the (regex)     pattern will be considered as defining aspects to use for Spring autoproxying.    ]]>    </xsd:documentation>   </xsd:annotation>   </xsd:element>   </xsd:sequence> - <xsd:attribute name="proxy-target-class" type="xsd:boolean" default="false"> - <xsd:annotation> - <xsd:documentation> - <![CDATA[      Are class-based (CGLIB) proxies to be created? By default, standard     Java interface-based proxies are created.    ]]>    </xsd:documentation>   </xsd:annotation>   </xsd:attribute> - <xsd:attribute name="expose-proxy" type="xsd:boolean" default="false"> - <xsd:annotation> - <xsd:documentation> - <![CDATA[      Indicate that the proxy should be exposed by the AOP framework as a     ThreadLocal for retrieval via the AopContext class. Off by default,     i.e. no guarantees that AopContext access will work.    ]]>    </xsd:documentation>   </xsd:annotation>   </xsd:attribute>   </xsd:complexType>   </xsd:element>

1.1 注册

org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator
的继承关系如下:

1.2 解析过程

AspectJAutoProxyBeanDefinitionParser.java#parse()方法

    public BeanDefinition parse(Element element, ParserContext parserContext) {         AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);         extendBeanDefinition(element, parserContext);         return null;     }

注册过程:

 public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(             ParserContext parserContext, Element sourceElement) {          BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(                 parserContext.getRegistry(), parserContext.extractSource(sourceElement));         useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);         registerComponentIfNecessary(beanDefinition, parserContext);     }

调用实现类:

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

1.3 具体实现类为:AbstractAutoProxyCreator的postProcessAfterInitialization()方法

DefaultAopProxyFactory#createAopProxy()方法

@Override     public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {         if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {             Class<?> targetClass = config.getTargetClass();             if (targetClass == null) {                 throw new AopConfigException("TargetSource cannot determine target class: " +                         "Either an interface or a target is required for proxy creation.");             }             if (targetClass.isInterface()) {                 return new JdkDynamicAopProxy(config);             }             return new ObjenesisCglibAopProxy(config);         }         else {             return new JdkDynamicAopProxy(config);         }     }

默认使用jdk自带的代理,还有一种cglib方式。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!