aop概念請(qǐng)參考
【http://www.iteye.com/topic/1122401】【http://jinnianshilongnian.iteye.com/blog/1418596】
spring的事務(wù)管理焰盗,請(qǐng)參考
注意看數(shù)字編號(hào)
也就是說我們首先調(diào)用的是AOP代理對(duì)象而不是目標(biāo)對(duì)象寄疏,首先執(zhí)行事務(wù)切面春寿,事務(wù)切面內(nèi)部通過TransactionInterceptor環(huán)繞增強(qiáng)進(jìn)行事務(wù)的增強(qiáng)渣玲,即進(jìn)入目標(biāo)方法之前開啟事務(wù)徐裸,退出目標(biāo)方法時(shí)提交/回滾事務(wù)崖堤。
簡單的一個(gè)例子
public interface AService {
public void a();
public void b();
}
@Service()
public class AServiceImpl1 implements AService{
@Transactional(propagation = Propagation.REQUIRED)
public void a() {
this.b();
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void b() {
}
}
此處的this指向目標(biāo)對(duì)象吗氏,因此調(diào)用this.b()將不會(huì)執(zhí)行b事務(wù)切面幅垮,即不會(huì)執(zhí)行事務(wù)增強(qiáng)乌昔,因此b方法的事務(wù)定義@Transactional(propagation = Propagation.REQUIRES_NEW)
將不會(huì)實(shí)施.
解決方案
此處a方法中調(diào)用b方法時(shí)隙疚,只要通過AOP代理調(diào)用b方法即可走事務(wù)切面,即可以進(jìn)行事務(wù)增強(qiáng)磕道。
public void a() {
aopProxy.b();//即調(diào)用AOP代理對(duì)象的b方法即可執(zhí)行事務(wù)切面進(jìn)行事務(wù)增強(qiáng)
}
判斷一個(gè)Bean是否是AOP代理對(duì)象可以使用如下三種方法:
AopUtils.isAopProxy(bean) : 是否是代理對(duì)象供屉;
AopUtils.isCglibProxy(bean) : 是否是CGLIB方式的代理對(duì)象;
AopUtils.isJdkDynamicProxy(bean) : 是否是JDK動(dòng)態(tài)代理方式的代理對(duì)象溺蕉;
方法一:通過ThreadLocal暴露Aop代理對(duì)象
1伶丐、開啟暴露Aop代理到ThreadLocal支持(如下配置方式從spring3開始支持)
<aop:aspectj-autoproxy expose-proxy="true"/><!—注解風(fēng)格支持-->
<aop:config expose-proxy="true"><!—xml風(fēng)格支持-->
2、修改我們的業(yè)務(wù)實(shí)現(xiàn)類
this.b();
-----------修改為--------->
((AService) AopContext.currentProxy()).b();
原理分析
1焙贷、在進(jìn)入代理對(duì)象之后通過AopContext.serCurrentProxy(proxy)暴露當(dāng)前代理對(duì)象到ThreadLocal撵割,并保存上次ThreadLocal綁定的代理對(duì)象為oldProxy;
2辙芍、接下來我們可以通過 AopContext.currentProxy() 獲取當(dāng)前代理對(duì)象啡彬;
3羹与、在退出代理對(duì)象之前要重新將ThreadLocal綁定的代理對(duì)象設(shè)置為上一次的代理對(duì)象,即AopContext.serCurrentProxy(oldProxy)庶灿。
有些人不喜歡這種方式纵搁,說通過ThreadLocal暴露有性能問題,其實(shí)這個(gè)不需要考慮往踢,因?yàn)槭聞?wù)相關(guān)的(Session和Connection)內(nèi)部也是通過SessionHolder和ConnectionHolder暴露到ThreadLocal實(shí)現(xiàn)的腾誉。
不過自我調(diào)用這種場(chǎng)景確實(shí)只有很少情況遇到,因此不用這種方式我們也可以通過如下方式實(shí)現(xiàn)峻呕。