首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

AOP 事宜缺陷

2012-11-07 
AOP 事务缺陷参考这个文档http://liuu.iteye.com/blog/422810?http://www.51cto.com/specbook/223/39480.h

AOP 事务缺陷

参考这个文档

http://liuu.iteye.com/blog/422810

?

http://www.51cto.com/specbook/223/39480.htm

?

http://www.iflym.com/index.php/code/proxy-created-of-subclass-extended-proxied-class-by-spring.html

?

http://www.iflym.com/index.php/code/proxy-method-intercept-of-subclass-extended-proxied-class-by-spring.html

?

http://www.iteye.com/problems/71797

?

http://www.iteye.com/topic/40553

?

http://www.redsaga.com/spring_ref/2.5/html/aop-api.html

?

http://japi.iteye.com/blog/285800

?

或许按照回复的办法,把参考文档中的两个方法放到不同类中。

很不幸,我也遇到了这个问题。

但是按照作者的方法,修改aop:config如下:

??? <aop:config proxy-target-expression="execution(* *..service.*Service.*(..)) " />
????? <aop:advisor pointcut-ref="allServiceMethod" advice-ref="txAdvice" />

? </aop:config>

其中service包下的是接口,具体实现在service.spring包下面。

修改后还是不行。

但改成这样就好了:

<aop:config>

<aop:pointcut id="allServiceMethod" expression="execution(* *..service.*Service.*(..)) and execution(* *..service.*.*Service.*(..))" />
<aop:advisor pointcut-ref="allServiceMethod" advice-ref="txAdvice" />

?</aop:config>

?

也就是在接口和实现类都声明在事务中。

?如果只是在声明接口或者实现类单方面加都不行。

修改后虽然能写数据库,但是事务不生效!!!很奇怪的问题!!!!

?

我的情况如下:

action调用service.A? ;serviceA调用service.B;

事务设置采用声明式事务

其中service.A的方法属于只读事务;B方法属于读写事务;然后B又调用service2.B,真正写数据库的是service2.B。

调用时报错,只读事务,不能修改数据。

查看堆栈发现,代理只在调用A时加了事务拦截,在A调用B是没加事务拦截;

堆栈大概如下,注意红色字体是连在一次调用,中间没有任何拦截:

?at xxx.service.spring.ServiceImpl.B(ServiceImpl.java:1245)
?at xxx.service.spring.ServiceImpl.A(ServiceImpl.java:1555)
?at xxx.service.spring.ServiceImpl$$FastClassByCGLIB$$5bad9769.invoke(<generated>)
?at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:149)
?at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:700)
?at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
?at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
?at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
?at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)
?at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
?at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:635)
?at xxx.action$$EnhancerByCGLIB$$f76d57d.xxx(<generated>)

?

?

?

如果是required,则事务依旧使用原来的事务,所以A只读,导致B只读,把service2.B改成REQUIRED_NEW就好了但没什么特殊要求都应该使用REQUIRED。

这个问题引起的原因是这个配置

?<tx:method name="*" propagation="REQUIRED" read-only="true"/>

导致A变成只读,范围太大了。

上面改后,service.B中依旧是只读事务。

?

测试发现AOP不能嵌套,不管JDK还是cglib都一样,如果同一对象OBJ的第一个函数A没有使用事务,那么A里面调用的OBJ.B方法,尽管B方法已经声明了事务,但一样不生效,因为AOP没有对A调用B是做拦截,也不可能做,B在OBJ中调用,不是在代理中调用,代理没法做。跨类到可以。

只读原因分析:

所以service.A只读事务,导致service.A调用B时,没经过AOP事务拦截,也就是service.A和service.B在同一个事务中,B就是只读事务,而当B调用service2.B时,如果service2.B是REQUIRED时,尽管service2.B的AOP拦截生效,但是REQUIRED命令service2.B直接使用已有事务,导致service2.B中也是只读事务。

?

?<tx:method name="*" propagation="REQUIRED" read-only="true"/>

去掉或者细化就好了

?

?

热点排行