Spring AOP 自动创建代理

版权声明:本文为博主原创文章,转载请指明文章出处! https://blog.csdn.net/u012385190/article/details/82114025

目录

 

1、概述

2、实现类介绍

3、BeanNameAutoProxyCreator的使用

4、DefaultAdvisorAutoProxyCreator


1、概述

在学习切面的时候,都是通过ProxyFactoryBean创建织入切面的代理,每个需要被代理Bean都需要使用一个ProxyFactoryBean进行配置,很是麻烦。Spring为我们提供了自动代理机制,Spring 使用BeanPostProcessor自动地完成这项工作,让容器为我们自动生成代理,把我们从烦琐的配置工作中解放出来。

 BeanPostProcessor接口如下,定义了两个方法

 public interface BeanPostProcessor {
 		Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
		Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}

2、实现类介绍

这些基于BeanPostProcessor的自动代理创建器的实现类,将根据一些规则自动在容器实例化Bean时为匹配的Bean生成代理实例。这些自动代理创建器可以分为3类。

a、基于Bean配置名规则的自动代理创建器:允许为一组特定配置名的Bean自动创建代理实例的代理创建器,实现类为BeanNameAutoProxyCreator;

b、基于Advisor匹配机制的自动代理创建器:它会对容器中所有的Advisor进行扫描,自动将这些切面应用到匹配的Bean中(即为目标Bean创建代理实例),实现类为DefaultAdvisorAutoProxyCreator;

c、基于Bean中AspjectJ注解标签的自动代理创建器:为包含AspectJ注解的Bean自动创建代理实例,它的实现类是AnnotationAwareAspectJAutoProxyCreator。

3、BeanNameAutoProxyCreator的使用

代码例子依旧使用前面创建切面的代码,创建切面的例子中是使用ProxyFactoryBean对Waiter的Bean创建代理对象(创建切面代码地址:https://blog.csdn.net/u012385190/article/details/81952302)。下面通过BeanNameAutoProxyCreator以更优雅、更便捷的方式来创建代理对象

xml配置如下

    <!-- 前置增强 -->
    <bean id="greetBeforeAdvice" class="demo04.advisor.GreetBeforeAdivce"/>

    <!-- Waiter目标类 -->
    <bean id="waiterTarget" class="demo04.advisor.Waiter"/>
    <!-- Seller目标类 -->
    <bean id="seller" class="demo04.advisor.Seller"/>
    <!--根据beanName创建代理对象-->
    <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"
          p:beanNames="*Target"
          p:interceptorNames="greetBeforeAdvice"
          p:optimize="true"/>

测试类

    //一组特定配置名的Bean自动创建代理实例的代理创建器
    @Test
    public void test() {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("beans/beans2.xml");
        Waiter waiter = ctx.getBean("waiterTarget", Waiter.class);
        Seller seller = ctx.getBean("seller", Seller.class);
        waiter.greetTo("JayChou");
        waiter.serverTo("JayChou");
        seller.greetTo("JayChou");
    }

输出(beanNames="*Target",该bean的方法都会使用增强)

How are you JayChou ?(切点方法为:public void demo04.advisor.Waiter.greetTo(java.lang.String))
Waiter Greet to JayChou
How are you JayChou ?(切点方法为:public void demo04.advisor.Waiter.serverTo(java.lang.String))
Waiter Server to JayChou
Seller Greet to JayChou

从输出结果可以看出,BeanNameAutoProxyCreator有一个beanNames属性,它允许用户指定一组需要自动创建代理的Bean名称,Bean名称可以使用 * 通配符。但是使用匹配符可能会匹配到多余的bean,所以也可以使用beanNames=“bean1,bean2”,用逗号分隔开多个要生成代理对象的bean。

4、DefaultAdvisorAutoProxyCreator

Advisor是切点和增强的复合体(切面),Advisor本身已经包含了足够的信息:横切逻辑(要织入什么)以及连接点(织入到哪里)。DefaultAdvisorAutoProxyCreator能够扫描容器中的Advisor,并将Advisor自动织入到匹配的目标Bean中,即为匹配的目标Bean自动创建代理。

<!--定义一个切面Advisor-->
<bean id="regexpAdvisor2" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"
          p:pattern=".*greet.*"
          p:advice-ref="greetingAdvice"/>
<!--该bean负责将容器中的Advisor织入匹配的目标bean中-->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>

测试

    @Test
    public void test() {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("beans/beans2.xml");
        Waiter waiter = ctx.getBean("waiterTarget", Waiter.class);
        Seller seller = ctx.getBean("seller", Seller.class);
        waiter.greetTo("JayChou");
        waiter.serverTo("JayChou");
        seller.greetTo("JayChou");
    }

输出

How are you JayChou ?(切点方法为:public void demo04.advisor.Waiter.greetTo(java.lang.String))
Waiter Greet to JayChou
Waiter Server to JayChou
How are you JayChou ?(切点方法为:public void demo04.advisor.Seller.greetTo(java.lang.String))
Seller Greet to JayChou

Waiter#serverTo()方法没有被织入增强,而Waiter和Seller的greetTo()方法都被织入了增强,由此可见,增强被正确的织入匹配的连接点中了。

猜你喜欢

转载自blog.csdn.net/u012385190/article/details/82114025