日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

浅谈spring之jdk动态代理

發布時間:2023/12/14 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 浅谈spring之jdk动态代理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

學習來源于b站動力節點

JDK動態代理

? 動態代理的實現方式常用的有兩種:使用JDK的Proxy,與通過CGLIB生成代理。jdk的動態要求目標對象必須實現接口,這是java設計上的要求,使用jdk中的Proxy,Method,InvocationHanderl創建代理對象。接下來演示jdk動態代理實現的一個小業務。
案例:

目前該項目主要完成業務doSome方法或doOther方法。(模擬項目開發,用注解獲取對象)

在service包下有SomeService接口(其中有doSome和doOther方法)。

package com.pingfan.bao05.service; public interface SomeService {void doSome();void doOther(); }

service包下有impl包以及impl包下有實現SomeService接口的類SomeServiceImpl

package com.pingfan.bao05.service.impl; import com.pingfan.bao05.service.SomeService; import org.springframework.stereotype.Component; @Component public class SomeServiceImpl implements SomeService {@Overridepublic void doSome() {System.out.println("執行業務方法doSome");}@Overridepublic void doOther() {System.out.println("執行業務方法doOther");} }

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"><context:component-scan base-package="com.pingfan.bao05"/> </beans>

測試:

@Test public void test02(){String config="applicationContext.xml";ApplicationContext ac=new ClassPathXmlApplicationContext(config);SomeServiceImpl someService= (SomeServiceImpl) ac.getBean("someServiceImpl");someService.doSome(); }

該項目運行一段時間需要改造,對業務增加功能。比如增加記錄時間的功能,和提交事務的功能。

對該功能可以在原有代碼基礎上實現:

對SomeServiceImpl進行修改

package com.pingfan.bao05.service.impl;import com.pingfan.bao05.service.SomeService; import org.springframework.stereotype.Component;import java.text.SimpleDateFormat; import java.util.Date;@Component public class SomeServiceImpl implements SomeService {@Overridepublic void doSome() {System.out.println("執行方法的時間"+new SimpleDateFormat("yyyy-MM-dd").format(new Date()));System.out.println("執行業務方法doSome");//提交事務System.out.println("方法執行完畢提交事務");}@Overridepublic void doOther() {System.out.println("執行方法的時間"+new SimpleDateFormat("yyyy-MM-dd").format(new Date()));System.out.println("執行業務方法doOther");System.out.println("方法執行完畢提交事務");} }

測試:

@Test public void test02(){String config="applicationContext.xml";ApplicationContext ac=new ClassPathXmlApplicationContext(config);SomeServiceImpl someService= (SomeServiceImpl) ac.getBean("someServiceImpl");someService.doSome();System.out.println("-----------");someService.doOther(); }

結果

執行方法的時間2021-01-16 執行業務方法doSome 方法執行完畢提交事務 ----------- 執行方法的時間2021-01-16 執行業務方法doOther 方法執行完畢提交事務

至此功能添加成功,如果像這種類很多,在開發中添加起來很多次,而且都是重復的操作。接下來對該項目進行優化,使得邏輯清晰。

增加一個工具類。ServiceTools。(把非業務方法放到工具類中)

package com.pingfan.bao05.utiles; import java.text.SimpleDateFormat; import java.util.Date; public class ServiceTools {public static void doLog(){System.out.println("非業務方法,執行方法的時間"+new SimpleDateFormat("yyyy-MM-dd").format(new Date()));}public static void doTrans(){System.out.println("方法執行完畢提交事務");} }

接下來使用jdk動態代理實現不改變原有代碼為其增加打印日志和提交事務的功能。

實現步驟:

  • 創建目標類,SomeServiceImpl類,給它的doSome,doOther增加日志和事務功能
  • 創建InvocationHandler接口的實現類,在這個類實現給目標方法增加功能。
  • 使用jdk中類Proxy,創建代理對象。實現創建對象的能力。
  • 1我們已經完成,接下來實現2

    MyIncationHandler.java

    package com.pingfan.bao05.handler;import com.pingfan.bao05.utiles.ServiceTools;import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method;public class MyIncationHandler implements InvocationHandler {//目標對象private Object targect;//SomeServiceImpl類public MyIncationHandler(Object targect){this.targect=targect;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//通過代理對象執行方法時,會調用執行這個invoke//執行目標類的方法,通過Method類實現。Object res=null;ServiceTools.doLog();res=method.invoke(targect,args);//SomeServiceImpl.doOther或者doSomeServiceTools.doTrans();//目標方法執行結果return res;} }

    實現步驟3

    @Test public void test02(){String config="applicationContext.xml";ApplicationContext ac=new ClassPathXmlApplicationContext(config);//使用jdk的Proxy創建代理對象,創建目標對象。SomeServiceImpl targect= (SomeServiceImpl) ac.getBean("someServiceImpl");//創建InvocationHandler對象InvocationHandler handler=new MyIncationHandler(targect);//使用Proxy創建代理SomeService proxy=(SomeService) Proxy.newProxyInstance(targect.getClass().getClassLoader(),targect.getClass().getInterfaces(),handler);//通過代理執行方法,會調用handler中的invokeproxy.doSome(); }

    結果

    非業務方法,執行方法的時間2021-01-16 執行業務方法doSome 方法執行完畢提交事務

    分析:首先執行proxy.doSome();他會執行proxy類中的handler類中的invake方法。而其中的method是通過jdk處理我們拿到的doSome,也就是Proxy.doSome,傳遞到了method,進而執行目標類的doSome方法,那我們就可以在此之前或者之后執行我們增加的功能。

    現在又有個需求,我們只在執行doSome方法時,才執行日志和事務功能。

    分析:通過獲取到的方法名進行判斷執行的方法,再進行增加功能。

    對MyIncationHandler進行修改。

    package com.pingfan.bao05.handler;import com.pingfan.bao05.utiles.ServiceTools;import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method;public class MyIncationHandler implements InvocationHandler {//目標對象private Object targect;//SomeServiceImpl類public MyIncationHandler(Object targect){this.targect=targect;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//通過代理對象執行方法時,會調用執行這個invoke//執行目標類的方法,通過Method類實現。Object res=null;if(method.getName().equals("doSome")){ServiceTools.doLog();res=method.invoke(targect,args);//SomeServiceImpl.doOther或者doSomeServiceTools.doTrans();}else{res=method.invoke(targect,args);//SomeServiceImpl.doOther或者doSome}//目標方法執行結果return res;} }

    測試:

    @Test public void test02(){String config="applicationContext.xml";ApplicationContext ac=new ClassPathXmlApplicationContext(config);//使用jdk的Proxy創建代理對象,創建目標對象。SomeServiceImpl targect= (SomeServiceImpl) ac.getBean("someServiceImpl");//創建InvocationHandler對象InvocationHandler handler=new MyIncationHandler(targect);//使用Proxy創建代理SomeService proxy=(SomeService) Proxy.newProxyInstance(targect.getClass().getClassLoader(),targect.getClass().getInterfaces(),handler);//通過代理執行方法,會調用handler中的invokeproxy.doSome();System.out.println("-----------");proxy.doOther(); }

    結果:

    非業務方法,執行方法的時間2021-01-16 執行業務方法doSome 方法執行完畢提交事務 ----------- 執行業務方法doOther

    總結:可以看到執行doSome方法時才會執行額外的功能。至此動態代理的實現完成,而我們接下來學習的aop他就是基于動態代理實現的,可以明顯的發現,我們在不改變源代碼的基礎上增加了新的功能,體現了動態代理的解耦合。實現業務和非業務功能分離。

    總結

    以上是生活随笔為你收集整理的浅谈spring之jdk动态代理的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。