Spring入门(AOP API,ProxyFactoryBean其三)

原创 2017年10月06日 17:37:18

Proxying classes

前面的ppt图片例子中如果没有Person接口,或者代码例子中没有BizLogic接口,这种情况下Spring会使用CGLIB代理,而不是JDK动态代理
如果想,可以强制在任何情况下使用CGLIB,即使有接口
CGLIB代理的工作原理是在运行时生成目标类的子类,Spring配置这个生成的子类委托方法调用到原来的目标
子类是用来实现Decorator模式,织入通知

CGLIB的代理对用户是透明的。需要注意:
-final方法不能被通知,因为它们不能被覆盖
-不用把CGLIB添加到classpath中,在Spring3.2中,CGLIB被重新包装并包含在Spring核心的JAR(即基于CGLIB的AOP就像JDK动态代理一样“开箱即用”)

使用global advisors

用*做通配符,匹配所有拦截器加入通知链

<bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="target" ref="service"/>
    <property name="interceptorNames">
        <list>
            <value>global*</value>
        </list>
    </property>
</bean>

<bean id="global_debug" class="org.springframework.aop.interceptor.DebugInterceptor"/>
<bean id="global_performance" class="org.springframework.aop.interceptor.PerformanceMonitorInterceptor"/>

在我们自己的例子中

    <bean id="bizLogicImpl" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="proxyInterfaces">
            <value>com.imooc.aop.api.BizLogic</value>
        </property>
        <property name="target">
            <bean class="com.imooc.aop.api.BizLogicImpl"></bean>
            <ref bean="bizLogicImplTarget"/>
        </property>
        <property name="interceptorNames">
            <list>
                <value>moocBeforeAdvice</value>
                <value>moocAfterReturningAdvice</value>
                <value>moocMethodInterceptor</value>
                <value>moocThrowsAdvice</value>
            </list>
        </property>
    </bean>

可以把list标签中的内容改为<value>mooc*</value>
执行后发现只执行了moocMethodInterceptor方法,因为只有*匹配匹配所有拦截器,那么拦截器是什么,是interceptor,只有MoocMethodInterceptor实现了MethodInterceptor,其他的几个advice还是要像之前一样逐个配置进去。

简化的proxy定义

在spring中支持使用父子bean定义,以及内部bean定义。可能会带来更清洁和更简洁的代理定义(抽象属性标记父bean定义为抽象的,这样它不能被实例化,可以理解和abstract class是一样的)

<bean id="txProxyTemplate" abstract="true" 
    class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    <property name="transacionManager" ref="transactionManager"/>
    <property name="transactionAttributes">
        <props>
            <prop key="*">PROPAGATION_REQUIRED</prop>
        </props>
    </property>
</bean>

接下来看如何来简化

<bean id="myService" parent="txProxyTemplate">
    <property name="target">
        <bean class="org.springframework.samples.MyServiceImpl>
        </bean>
    </property>
</bean>

parent是txProxyTemplate,也就是上边定义的bean的id。使用属性target,指向MyServiceImpl实现类。注意这个target,是parent里面的属性,在继承的时候可以为parent进行赋值。
再看下边这个例子:

<bean id="mySpecialService" parent="txProxyTemplate">
    <property name="target">
        <bean class="org.springframework.samples.MySpecialServiceImpl>
        </bean>
    </property>
    <property name="transactionAttributes">
        <props>
            <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
            <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
            <prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>
            <prop key="store*">PROPAGATION_REQUIRED</prop>
        </props>
    </property>
</bean>

parent和上边一样,target属性指向MySpecialServiceImpl这个实现类,同时,可以覆盖掉parent里边的transactionAttributes属性。

看一下我们自己之前的代码要如何实现

     <bean id="moocBeforeAdvice" class="com.imooc.aop.api.MoocBeforeAdvice"></bean>

     <bean id="moocAfterReturningAdvice" class="com.imooc.aop.api.MoocAfterReturningAdvice"></bean>

     <bean id="moocMethodInterceptor" class="com.imooc.aop.api.MoocMethodInterceptor"></bean>

     <bean id="moocThrowsAdvice" class="com.imooc.aop.api.MoocThrowsAdvice"></bean>

    <bean id="baseProxyBean" class="org.springframework.aop.framework.ProxyFactoryBean" 
            lazy-init="true" abstract="true"></bean>

    <bean id="bizLogicImpl"  parent="baseProxyBean">
        <property name="target">
            <bean class="com.imooc.aop.api.BizLogicImpl"></bean>
        </property>
        <property name="proxyInterfaces">
            <value>com.imooc.aop.api.BizLogic</value>
        </property>
        <property name="interceptorNames">
            <list>
                <value>moocBeforeAdvice</value>
                <value>moocAfterReturningAdvice</value>
                <value>moocMethodInterceptor</value>
                <value>moocThrowsAdvice</value>
            </list>
        </property>
    </bean>

定义baseProxyFactory,指向ProxyFactoryBean。然后是定义自己的beanbizLogicImpl,parent是baseProxyFactory,同时在当前的bean里边设置target。然后是proxyInterfaces和interceptorNames,唯一有区别的就是指定了parent,通过parent来指向ProxyFactoryBean。
运行单元测试的结果没有变化

使用ProxyFactory

使用Spring AOP而不必依赖于Spring IOC(这是一种好处),使用方式:

ProxyFactory factory=new ProxyFactory(myBusinessInterfaceImpl);
factory.addAdvice(myMethodInterceptor);
factory.addAdvisor(myAdvisor);
MyBusinessInterface tb=(MyBusinessInterface)factory.getProxy();

声明并创建ProxyFactory的对象,并把某一个对象赋值给它,然后addAdvice和addAdvisor,最后通过getProxy得到它所代理的那个对象。

大多数情况下最佳实践是用IOC容器创建AOP代理
虽然可以硬编码方式实现,但是Spring推荐使用配置或注解方式实现

使用“auto-proxy”

Spring也允许使用“自动代理”的bean定义,它可以自动代理选定的bean,这是建立在Spring的“bean post processor”功能基础上的(在加载bean的时候就可以修改)
主要通过BeanNameAutoProxyCreator来实现

<bean class="org.springframework.aop.framework.BeanNameAutoProxyCreator">
    <property name="beanNames" value="jdk*,onlyJdk"/>
    <property name="interceptorNames">
        <list>
            <value>myInterceptor</value>
        </list>
    </property>
</bean>

它会代理所有以jdk开始的这种bean,也包括onlyJdk,否则就会像刚才一样,每一个bean挨个指定parent或者最原始的方式,所以好处就是可以简化配置和开发。

使用DefaultAdvisorAutoProxyCreator,当前IOC容器中自动应用,不用显示声明引用advisor的bean定义。

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

<bean class="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor">
    <property name="transactionInterceptor" ref="transactionInterceptor"/>
</bean>

<bean id="customAdvisor" class="com.mycompany.Myadvisor"/>

<bean id="businessObject1" class="com.mycompany.BusinessObject1"></bean>

<bean id="businessObject2" class="com.mycompany.BusinessObject2"></bean>

如果在当前的IOC容器声明了第一行,也就是DefaultAdvisorAutoProxyCreator这样的bea,那么它会在当前的IOC容器中自动应用,来达到创建代理的效果,使用它的时候不用显示引用advisor的bean定义

版权声明:本文为博主原创文章,未经博主允许不得转载。

spring aop(五)--ProxyFactoryBean创建代理的实现

先看看ProxyFactoryBean的类层次结构. ProxyFactoryBean实现了FactoryBean,最终通过getObject方法生成Bean,所以getObject方法是个入口...
  • xiejx618
  • xiejx618
  • 2015年02月14日 12:27
  • 2988

做一个合格的程序猿之浅析Spring AOP源码(十四) 分析ProxyFactoryBean

最基本的实现有三个,AspectJProxyFactory.java ,ProxyFactory.java ProxyFactoryBean这三个,他们的父类ProxyCreatorSupport只是...
  • linuu
  • linuu
  • 2016年03月24日 15:20
  • 3920

spring 直接使用ProxyFactoryBean 实现AOP 流程小结

com\.daodao\.mybatis\..*
  • u011385186
  • u011385186
  • 2017年05月07日 22:26
  • 341

Spring源码分析之ProxyFactoryBean方式实现Aop功能的分析

实现Aop功能有两种方式, 1. ProxyFactoryBean方式: 这种方式是通过配置实现 2. ProxyFactory方式:这种方式是通过编程实现 这里只说ProxyFactoryBean方...
  • u011734144
  • u011734144
  • 2017年06月18日 19:36
  • 1468

SpringAOP(一) ProxyFactoryBean

SpringAOP主要是通过动态代理技术。
  • is_zhoufeng
  • is_zhoufeng
  • 2014年08月07日 18:54
  • 2431

Spring入门(AOP API、ProxyFactoryBean其一)

介绍这是Spring1.2历史用法,现在(V4.0)仍然支持 这是SpringAOP基础,不得不了解 现在的用法也是基于历史的,只是更简便了PointcutPointcut作为一个接口,它有几个实...
  • qq_36206746
  • qq_36206746
  • 2017年10月04日 23:45
  • 81

Spring入门(AOP API、ProxyFactoryBean其二)

ProxyFactoryBean 这个类是Spring AOP代理的最基础核心的一个类 创建Spring AOP代理的基本方法是使用org.springframework.aop.framewor...
  • qq_36206746
  • qq_36206746
  • 2017年10月05日 01:45
  • 78

【框架】[Spring]AOP拦截-三种方式实现自动代理

转载请注明出处:http://blog.csdn.net/qq_26525215 本文源自【大学之旅_谙忆的博客】 这里的自动代理,我讲的是自动代理bean对象,其实就是在xml中让我们不用配置代理工...
  • qq_26525215
  • qq_26525215
  • 2016年09月03日 00:15
  • 4224

Spring入门(Schema-based AOP其三)

Advice应用配置完了切入点,接下来要配置advice,也就是通知的配置。Before adviceBefore advice是前置通知前置通知的方式是aop:before,然后有一个pointcu...
  • qq_36206746
  • qq_36206746
  • 2017年10月03日 17:17
  • 61

Spring AOP入门——概念及注意点

Spring AOP入门——概念及注意点
  • u012345283
  • u012345283
  • 2014年08月20日 09:15
  • 1899
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Spring入门(AOP API,ProxyFactoryBean其三)
举报原因:
原因补充:

(最多只允许输入30个字)