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

最近再看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配置比较集中,很清晰,也很简单。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值