當前位置:
首頁 >
前端技术
> javascript
>内容正文
javascript
Spring事务“套路”面试
生活随笔
收集整理的這篇文章主要介紹了
Spring事务“套路”面试
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
回復”666“獲取公眾號專屬資料
記一次“帶套路”的面試
//接口 interface?Service?{void?doNeedTx();void?doNotneedTx(); }//目標類,實現接口 class?ServiceImpl?implements?Service?{@Transactional@Overridepublic?void?doNeedTx()?{System.out.println("execute?doNeedTx?in?ServiceImpl");}//no?annotation?here@Overridepublic?void?doNotneedTx()?{this.doNeedTx();} }//代理類,也要實現相同的接口 class?ProxyByJdkDynamic?implements?Service?{//包含目標對象private?Service?target;public?ProxyByJdkDynamic(Service?target)?{this.target?=?target;}//目標類中此方法帶注解,進行特殊處理@Overridepublic?void?doNeedTx()?{//開啟事務System.out.println("->?create?Tx?here?in?Proxy");//調用目標對象的方法,該方法已在事務中了target.doNeedTx();//提交事務System.out.println("<-?commit?Tx?here?in?Proxy");}//目標類中此方法沒有注解,只做簡單的調用@Overridepublic?void?doNotneedTx()?{//直接調用目標對象方法target.doNotneedTx();} } //是否是JDK動態代理 System.out.println("isJdkDynamicProxy?=>?"?+?AopUtils.isJdkDynamicProxy(exampleService)); //是否是CGLIB代理 System.out.println("isCglibProxy?=>?"?+?AopUtils.isCglibProxy(exampleService)); //代理類的類型 System.out.println("proxyClass?=>?"?+?exampleService.getClass()); //代理類的父類的類型 System.out.println("parentClass?=>?"?+?exampleService.getClass().getSuperclass()); //代理類的父類實現的接口 System.out.println("parentClass's?interfaces?=>?"?+?Arrays.asList(exampleService.getClass().getSuperclass().getInterfaces())); //代理類實現的接口 System.out.println("proxyClass's?interfaces?=>?"?+?Arrays.asList(exampleService.getClass().getInterfaces())); //代理對象 System.out.println("proxy?=>?"?+?exampleService); //目標對象 System.out.println("target?=>?"?+?AopProxyUtils.getSingletonTarget(exampleService)); //代理對象和目標對象是不是同一個 System.out.println("proxy?==?target?=>?"?+?(exampleService?==?AopProxyUtils.getSingletonTarget(exampleService))); //目標類的類型 System.out.println("targetClass?=>?"?+?AopProxyUtils.getSingletonTarget(exampleService).getClass()); //目標類實現的接口 System.out.println("targetClass's?interfaces?=>?"?+?Arrays.asList(AopProxyUtils.getSingletonTarget(exampleService).getClass().getInterfaces()));System.out.println("----------------------------------------------------");//自己模擬的動態代理的測試 Service?target?=?new?ServiceImpl(); ProxyByJdkDynamic?proxy?=?new?ProxyByJdkDynamic(target); proxy.doNeedTx(); System.out.println("-------"); proxy.doNotneedTx(); System.out.println("-------");以下是輸出結果:
//是JDK動態代理 isJdkDynamicProxy?=>?true //不是CGLIB代理 isCglibProxy?=>?false //代理類的類型,帶$的 proxyClass?=>?class?com.sun.proxy.$Proxy82 //代理類的父類 parentClass?=>?class?java.lang.reflect.Proxy 代理類的父類實現的接口 parentClass's?interfaces?=>?[interface?java.io.Serializable] //代理類實現的接口,包含了目標類的接口IExampleService,還有其它的 proxyClass's?interfaces?=>?[interface?org.eop.sb.example.service.IExampleService, interface?org.springframework.aop.SpringProxy, interface?org.springframework.aop.framework.Advised, interface?org.springframework.core.DecoratingProxy] //代理對象 proxy?=>?org.eop.sb.example.service.impl.ExampleServiceImpl@54561bc9 //目標對象 target?=>?org.eop.sb.example.service.impl.ExampleServiceImpl@54561bc9 //代理對象和目標對象輸出的都是@54561bc9,還真有點懵逼 //進行測試后發現,其實不是同一個,只是toString()的問題 proxy?==?target?=>?false //目標類,我們自己寫的 targetClass?=>?class?org.eop.sb.example.service.impl.ExampleServiceImpl //目標類實現的接口,我們自己寫的 targetClass's?interfaces?=>?[interface?org.eop.sb.example.service.IExampleService] ---------------------------------------------------- //帶注解的方法調用,有事務的開啟和提交 ->?create?Tx?here?in?Proxy execute?doNeedTx?in?ServiceImpl <-?commit?Tx?here?in?Proxy ------- //沒有注解的方法調用,是沒有事務的 execute?doNeedTx?in?ServiceImpl ------- class?Target?{@Transactionalpublic?void?doNeedTx()?{System.out.println("execute?doNeedTx?in?Target");}//no?annotation?herepublic?void?doNotneedTx()?{this.doNeedTx();} }class?ProxyByCGLIB?extends?Target?{private?Target?target;public?ProxyByCGLIB(Target?target)?{this.target?=?target;}@Overridepublic?void?doNeedTx()?{System.out.println("->?create?Tx?in?Proxy");target.doNeedTx();System.out.println("<-?commit?Tx?in?Proxy");}@Overridepublic?void?doNotneedTx()?{target.doNotneedTx();} } //不是JDK動態代理 isJdkDynamicProxy?=>?false //是CGLIB代理 isCglibProxy?=>?true //生成的代理類的類型,帶$$的 proxyClass?=>?class?org.eop.sb.example.service.impl.ExampleServiceImpl$$EnhancerBySpringCGLIB$$5320b86e //代理類的父類,就是目標類 parentClass?=>?class?org.eop.sb.example.service.impl.ExampleServiceImpl //父類實現的接口,就是我們自己寫的接口 parentClass's?interfaces?=>?[interface?org.eop.sb.example.service.IExampleService] /**代理類實現的接口,并不包含目標類的接口*/ proxyClass's?interfaces?=>?[interface?org.springframework.aop.SpringProxy, interface?org.springframework.aop.framework.Advised, interface?org.springframework.cglib.proxy.Factory] //代理對象 proxy?=>?org.eop.sb.example.service.impl.ExampleServiceImpl@1b2702b1 //目標對象 target?=>?org.eop.sb.example.service.impl.ExampleServiceImpl@1b2702b1 //代理對象和目標對象不是同一個 proxy?==?target?=>?false //目標類,我們自己寫的類 targetClass?=>?class?org.eop.sb.example.service.impl.ExampleServiceImpl //目標類實現的接口 targetClass's?interfaces?=>?[interface?org.eop.sb.example.service.IExampleService]由于采用的是相同的測試代碼,所以目標類是實現了接口的,不過這并不影響使用CGLIB來生成代理。可見,代理類確實繼承了目標類以保持和目標類的類型兼容,對外接口相同。注:只要是以代理方式實現的聲明式事務,無論是JDK動態代理,還是CGLIB直接寫字節碼生成代理,都只有public方法上的事務注解才起作用。而且必須在代理類外部調用才行,如果直接在目標類里面調用,事務照樣不起作用。
后記
想知道更多?掃描下面的二維碼關注我
加技術群入口(備注:Tech):
免費星球入口:
免費資料入口:后臺回復“666”
朕已閱?
超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生總結
以上是生活随笔為你收集整理的Spring事务“套路”面试的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 为什么说Prometheus是足以取代Z
- 下一篇: 细数 Spring 那些最常见的面试问题