spring学习笔记(七)

前言

        春节放假归来,收心继续工作学习,前面的笔记介绍了Spring AOP的简单使用,但使用ProxyFactoryBean创建织入切面的代理时,每一个需要代理的Bean都需要一个ProxyFactoryBean配置,在有很多的Bean都需要代理时,将增加大量的配置信息,而且这些配置信息有很多都是相同的,这种情况下就应该使用Spring提供的自动创建代理了。

自动创建代理

        在内部,Spring使用BeanPostProcessor完成自动创建代理的工作,而BeanPostProcessor的自动代理创建起的实现类,根据匹配规则的不同大概分成了三类:

  • 匹配Bean的名称自动创建匹配到的Bean的代理,实现类BeanNameAutoProxyCreator

  • 根据Advisor的匹配机制自动创建代理,会对容器中所有的Advisor进行扫描,自动将这些切面应用到匹配的Bean中,实现类DefaultAdvisorAutoProxyCreator

  • 根据Bean中的AspectJ注解自动创建代理,实现类AnnotationAwareAspectJAutoProxyCreator

BeanNameAutoProxyCreator

        例:现在有一个Waiter类和Seller类都需要织入GreetingBeforeAdvice的增强,使用BeanNameAutoProxyCreator自动创建代理我们可以如下配置:

......
<bean id="waiter" class="com.advisor.Waiter"/>
<bean id="seller" class="com.advisor.Seller"/>
<bean id="advisor" class="com.advisor.GreetingBeforeAdvice" />

<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"
    p:beanNames="*er"
    p:interceptorNames="advisor"
    p:optimize="true" />

BeanNameAutoProxyCreator中的beanNames属性值用来匹配其他Bean的名称,例子中*er表示匹配Bean名称以er结尾的Bean织入GreetingBeforeAdvice增强,BeanNameAutoProxyCreator会自动创建代理,使用时直接用获取对应的Bean返回的其实已经是代理对象了

DefaultAdvisorAutoProxyCreator

        例:现在有一个Waiter类和Seller类,他们都有一个greetTo()方法,我们希望为两个类中的这个方法都织入GreetingBeforeAdvice增强

......
<bean id="waiter" class="com.advisor.Waiter"/>
<bean id="seller" class="com.advisor.Seller"/>
<bean id="advice" class="com.advisor.GreetingBeforeAdvice" />
<bean id="advisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"
    p:patterns=".*greetTo.*"
    p:advice-ref="advice" />

<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" />

DefaultAdvisorAutoProxyCreator会对容器中所有的Advisor进行扫描,自动将这些切面应用到匹配的Bean中

AnnotationAwareAspectJAutoProxyCreator

        使用AnnotationAwareAspectJAutoProxyCreator自动创建代理需要先学习AspectJ表达式,这里就不详细讲解AspectJ表达式了,需要学习的请参考:spring AspectJ的Execution表达式 AspectJ表达式除了execution还有其他的如args()、within()、target()等,有兴趣可以自行研究。

        例:使用Aspect实现上同样的例子,在advisor中需要加入AspectJ注解

......

@AspectJ
public class GreetingBeforeAdvisor {
    @Before("execution (* greetTo(..))")
    public void beforeGreeting() {
        ......
    }
}

可以看到现在GreetingBeforeAdvice没有继承任何类,或实现任何接口,@AspectJ已经标注了他是一个切面,而方法上的@Before()表示下面方法中的代码是前置增强的横切逻辑。然后只需要在配置文件中配置:

......
<bean id="waiter" class="com.advisor.Waiter"/>
<bean id="seller" class="com.advisor.Seller"/>
<bean id="advice" class="com.advisor.GreetingBeforeAdvisor" />

<bean class="org.springframework.aop.aspectJ.annotation.AnnotationAwareAspectJAutoProxyCreator" />
<!-- 或者也可以直接使用aop命名空间
<aop:aspectj-autoproxy />
 -->

不同的增强对应的AspectJ注解

        @Before

        对应前置增强,有两个成员:

    • value:用于定义切点(使用AspectJ表达式)

    • argNames:用于一共方法的参数名称(必须与方法参数名称一致,可选成员),由于Java反射机制不能够得到方法的入参名称,有需要时可以用这个成员变量提供出来

    @AfterReturning

    对应后置增强,有四个成员:

    • value:同上

    • pointcut:表示切点信息,可以显示指定pointcut,若指定覆盖value效果

    • returning:邦队目标对象方法放回增强方法中

    • argNames:同上

    @Around

    对应环绕增强,成员value、argNames同上

    @AfterThrowing

    异常抛出增强,有4个成员

    • value:同上

    • pointcut:同上

    • throwing;将抛出的异常绑定到增强中

    • argNames:同上

    @After

    没有对应的增强接口,不管是抛出异常还是正常退出总会得到执行,一般用来释放资源,value、argNames同上

    @DeclareParents

    对应引介增强


你可能感兴趣的:(spring,AOP,自动创建代理)