当前位置: 代码迷 >> 综合 >> spring基本使用(14)-springAOP的使用以及原理4 springAOP的aop命名空间
  详细解决方案

spring基本使用(14)-springAOP的使用以及原理4 springAOP的aop命名空间

热度:38   发布时间:2023-10-24 15:49:19.0

1、SpringAOP的aop命名空间的基本使用

     1.1、非AspectJ注解的使用形式

 目标bean定义   <bean id="aopNameSpaceTestBean" class="com.wzy.springstudy.aop.AutoProxyCreator.aopnamespace.AopNameSpaceTestBean"/>aspect bean定义 非注解方式,就是普通的类<bean id="aspectJBean" class="com.wzy.springstudy.aop.AutoProxyCreator.aopnamespace.AspectJBean"/>aop配置<aop:config proxy-target-class="true"><aop:aspect ref="aspectJBean" order="1"><aop:pointcut id="aspectPointcut" expression="execution(* com.wzy.springstudy.aop.AutoProxyCreator.aopnamespace.AopNameSpaceTestBean.test())"/><aop:before pointcut-ref="aspectPointcut" method="sayHello"/></aop:aspect></aop:config>public class AopNameSpaceTestBean {public void test(){System.out.println("ttttttttt");}
}public class AspectJBean {public void sayHello(){System.out.println("hello");}
}@Testpublic void testAopNameSpace(){ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-context-aopAutoCreator.xml");com.wzy.springstudy.aop.AutoProxyCreator.aopnamespace.AopNameSpaceTestBean aopNameSpaceTestBean = (AopNameSpaceTestBean) ctx.getBean("aopNameSpaceTestBean");aopNameSpaceTestBean.test();}输出:hello         逻辑织入成功ttttttttt

        1.2、AspectJ注解的使用形式

                使用AspectJ的注解定义好切面,然后在xml中添加:<aop:aspectj-autoproxy proxy-target-class="true" expose-proxy="true"/> 即可。

 

2、aop命名空间的实现原理分析

        2.1、AopNamespaceHandler源码:

public class AopNamespaceHandler extends NamespaceHandlerSupport {/*** Register the {@link BeanDefinitionParser BeanDefinitionParsers} for the* '{@code config}', '{@code spring-configured}', '{@code aspectj-autoproxy}'* and '{@code scoped-proxy}' tags.*/init方法的执行时机是xml文件解析的时候@Overridepublic void init() {// In 2.0 XSD as well as in 2.1 XSD.添加一个ConfigBeanDefinitionParser bean定义解析器,专门用于解析<aop:config 及其子标签registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());添加一个AspectJAutoProxyBeanDefinitionParser同于注册一个AspectJAutoProxyBeanDefinitionParser用于解析<aop:aspectj-autoproxy标签registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());添加一个ScopedProxyBeanDefinitionDecorator 用于解析 <aop:scoped-proxy标签registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());// Only in 2.0 XSD: moved to context namespace as of 2.1registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());}

        2.2、我们先来查看非AspectJ注解的使用形式原理,我们主要查看的是ConfigBeanDefinitionParser类因为它是用来解析<aop:config标签的,其源码如下:我们主要看它的parse()方法

	@Overridepublic BeanDefinition parse(Element element, ParserContext parserContext) {CompositeComponentDefinition compositeDef =new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));parserContext.pushContainingComponent(compositeDef);配置一个代理自动构建器,这里构建的是AspectJAwareAdvisorAutoProxyCreator构建器 非注解的AspectJ的代理构建器!!!!!configureAutoProxyCreator(parserContext, element);List<Element> childElts = DomUtils.getChildElements(element);for (Element elt: childElts) {String localName = parserContext.getDelegate().getLocalName(elt);if (POINTCUT.equals(localName)) {解析<aop:pintcut 元素,生成一个BeanDefinition实例注册到BeanDefinitionRegistry中parsePointcut(elt, parserContext);}else if (ADVISOR.equals(localName)) {解析<aop:advisor 元素,生成一个BeanDefinition实例注册到BeanDefinitionRegistryparseAdvisor(elt, parserContext);}else if (ASPECT.equals(localName)) {解析<aop:aspect 元素,生成一个BeanDefinition实例注册到BeanDefinitionRegistryparseAspect(elt, parserContext);}}parserContext.popAndRegisterContainingComponent();return null;}

                   实现就是这么简单,解析标签 生成响应的BeanDefinition实例注册到容器中。

        2.3、AspectJ注解的使用形式的实现原理

                这种使用方法比较简洁,也是推荐的使用方式,其实现原理也很简单,就是像容器中注册一个基于AspectJ注解形式处理的代理自动构建器AnnotationAwareAspectJAutoProxyCreator 我们来查看AspectJAutoProxyBeanDefinitionParser的源码,同样也是查看其parse()方法:

	@Overridepublic 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) {最终就只是需要注册一个AnnotationAwareAspectJAutoProxyCreator的beanDefinition的实例到IOC容器中即可。return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);}

3、SpringAOP总结:

      1、我们通过4篇博客讲解了SpringAop的基本使用以及实现原理,主要讲解的东西有AOP的基本定义、AOP术语的解释、SpringAOP的代理技术、SpringAOP对AspectJ的语法支持。

      2、重点讲解了代理自动构建器AbstractAutoProxyCreator 以及主要的实现:

                 BeanNameAutoProxyCreator、DefaultAdvisorAutoProxyCreator、AnnotationAwareAspectJAutoProxyCreator

     3、AopNameSpaceHandler 的主要实现方式。

     对于SpringAOP内部实现的一些经典的切点以及切面我们不做太多解释,还有AspectJ的一些切点表达式函数我们也没有太多的提及,因为这些东西是需要记忆的,我们只需要以查字典的方式去查找使用即可,我们还是主要偏向于整体的实现。

 

 

 

 

 

 

  相关解决方案