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

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");
    }
}

    @Test
    public 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文件解析的时候
	@Override
	public 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.1
		registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
	}

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

	@Override
	public 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实例注册到BeanDefinitionRegistry
				parseAdvisor(elt, parserContext);
			}
			else if (ASPECT.equals(localName)) {
                     解析<aop:aspect 元素,生成一个BeanDefinition实例注册到BeanDefinitionRegistry
				parseAspect(elt, parserContext);
			}
		}

		parserContext.popAndRegisterContainingComponent();
		return null;
	}

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

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

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

	@Override
	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) {

                最终就只是需要注册一个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的一些切点表达式函数我们也没有太多的提及,因为这些东西是需要记忆的,我们只需要以查字典的方式去查找使用即可,我们还是主要偏向于整体的实现。

 

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值