关闭

spring2.0 aop -- 被myeclipse和spring忽悠了,升级升级!spring2.0.7

标签: springaopmyeclipsebeanschemaclass
1875人阅读 评论(0) 收藏 举报

最近再看spring的aop--算是深入研究把--以前怎么就一知半解的用了这么久~~

spring aop有2种方式,jdk dynamic proxy和cglib,反正觉得前者没什么用,而且后者的效率据相关测试应该是比较快的,所以我一般都会把proxyTargetClass设置成true :)

顺便也说下cglib:

cglib借助于asm(很小巧的一个操纵java bytecode的开源包)来动态生成类--在aop应用中也就是生成需要proxy的类(target/目标类)的子类(proxy/代理类),同时代理类包装/代理了target实例的所有方法,这样就能对 target的方法 进行拦截拉(其实就是装饰器模式) :)

继续回来spring aop,据说spring1.0 是不可以proxy 一个实例2次的(只是据说拉,因为我用spring1.2.8是可以的)。接下来说下spring1和2在aop上的一些不同。

spring1

事务代理是spring aop中用到最多的,以前spring里配置事务aop时大多数人都是写一个proxyfactorybean,好一点的写一个baseTxService,然后parent="baseTxService",反正看到这样的写法,我是很晕的--没有一种能够不改变bean配置就能进行事务代理的方法吗?--spring的声明性事务应该更彻底些啊!答案是,有办法,请看这里:

 http://www.javaeye.com/topic/19317?page=1

这个帖子基本把问题说清楚了。总结一下就是 一下的配置:

 

<beans>    
        
<!-- Transaction manager for a single Hibernate SessionFactory (alternative to JTA) -->    
    
<bean id="transactionManager"           class="org.springframework.orm.hibernate3.HibernateTransactionManager">    
          
<property name="sessionFactory">    
              
<ref bean="sessionFactory"/>    
          
</property>    
    
</bean>           
           
        
<bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">    
            
<property name="transactionManager" ref="transactionManager"/>    
            
<property name="transactionAttributes">  
                
<props>  
                    
<prop key="*">PROPAGATION_REQUIRED</prop>  
                    
<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>  
                
</props>  
            
</property>  
        
</bean>    
           
        
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">    
                
<property name="beanNames">  
                    
<value>*Service,*Manager</value>  
                
</property>  
                
<property name="interceptorNames">    
                        
<list>    
                                
<value>transactionInterceptor</value>    
                        
</list>    
                
</property>    
        
</bean>    
  
        
<bean id="userManager" class="some.package.UserManagerImpl" autoWire="byName"/>  
                   
</beans>   

很清爽吧,bean和事务的aop完全分开了,奥秘就在于 BeanNameAutoProxyCreator 拉,BeanNameAutoProxyCreator 继承 AbstractAutoProxyCreator ,具体关系请看下面的图:

AbstractAutoProxyCreator 可是干了很多事情啊,而且很有意思的--就是实现了InstantiationAwareBeanPostProcessor 接口,使得它能够在每一个bean初始化好后(当然还有实例化前,实例化后的方法处理),做一个拦截,并返回该bean的实例(想想啊,这样就可以修改raw bean了吧,其实就是在初始化好后用cglib wrap该bean原来的实例,并把cglib新生成的实例返回给beanfactory),好玩的:)

 

但是spring1里的aop我个人感觉存在一个比较混乱的局面,而且这种代理的模式会导致多次代理,而且通过proxyfactorybean代理出来的bean再用AutoProxyCreator代理好像会有问题(order不起作用,无法定义切面拦截器的优先级),当然拉,都用AutoProxyCreator就没有这种问题,order运行良好(这里的order是基于BeanPostProcessor的,也就是factory级别的排序,这也是导致下面性能问题的主要因素)。

最后是性能问题。如果你有很多切面的话,并且切面重复应用于很多相同的bean,也就是一个bean对应多个切面的话,那么效率可能会差一点(每个AutoProxyCreator都会实例化bean一次,然后cglib的生成总是基于上一个AutoProxyCreator生成的代理对象,有点浪费,代理会多好几个层--你有几个aop就有几层代理)

spring2

  spring2的aop果然很大改动。aop文档开篇就介绍@Aspect注解方式的配置,其实我觉得统一aop的配置方式,并且使得它更加易用才是这次改动的成功之处。

初看schema的配置方式就觉得spring2应该是用AutoProxyCreator来实现的。经过调看src,发现果然如此;同时关注了下order的实现,期望新引入的aspect和原来的advisor能并行。

(理论应该如此,可实际上spring2发布的时候aspect并没有实现order,然后我的myeclipse的xml编辑器好像用了最新的aop schema,导致我写xml的时候是可以写order,我还暗喜,然后运行就出错了~~;然后去了spring官网,看看是不是schema的问题;看了spring2.0.7的changelog后发现这个特性才加上~~~bug!!!不管怎么说,现在是好了,所以切记,整数的release版本是很危险的)spring2.0.7以后修复/添加了order属性,使得aspect和advisor都能很好的并存,对spring来说都是advisor/advice  拉 ^_^ 。 

看了spring2.0.7后发现aop那块的代码在2.0.0到2.0.7中大改了,有一个原来用来加载aop config的类都没有了(或者是改名了)~~。现在的aop实现基本上是这样:

AspectJAwareAdvisorAutoProxyCreator 作为启用<aop:...>的默认AutoProxyCreator(如果你使用了<aop:aspectj-autoproxy/>的话AutoProxyCreator会换成AnnotationAwareAspectJAutoProxyCreator)不过其实只是添加了搜索bean中标记了@Aspect的实例作为可用的advisor而已;order的排序方式好像也有改动,现在的排序没有什么问题。

性能上,由于采用了单一的AspectJAwareAdvisorAutoProxyCreator ,作为唯一的advisor配置库,在其中进行advisor的排序,所以再多的切面也只需要实例化一个bean的对象,切面在一个层次上进行,看似没有以前那么臃肿拉 :)

spring2的aop配置比较集中,很清晰,也很简单。

 

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:49577次
    • 积分:1078
    • 等级:
    • 排名:千里之外
    • 原创:58篇
    • 转载:3篇
    • 译文:0篇
    • 评论:4条
    最新评论