国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

JDK動態代理

2019-11-11 06:00:07
字體:
來源:轉載
供稿:網友
1、背景   SPRing AOP使用動態代理技術在運行期織入增強的代碼,Spring AOP 的底層使用了兩種代理模式一種是JDK的動態代理,另一種是基于CGLIB的動態代理。之所以需要兩種代理機制,很大程度上是因為JDK本身只提供接口的代理,而不支持類的代理。  2、JDKProxy的代碼package com.itheima.spring.jdkproxy;public interface PersonDao { public void savePerson();}package com.itheima.spring.jdkproxy;public class PersonDaoImpl implements PersonDao{ @Override public void savePerson() { System.out.println("save person"); }}package com.itheima.spring.jdkproxy;public class Transaction { public void beginTransaction(){ System.out.println("begin transcation"); } public void commit() { System.out.println("commit"); }}package com.itheima.spring.jdkproxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;/** * 攔截器: * 1、目標類導入進來 * 2、事務導入進來 * 3、invoke完成 * ①開啟事務 * ②調用目標對象的方法 * ③事務提交 * @author xx * */public class MyInterceptor implements InvocationHandler{ private Object target; //目標類 private Transaction transaction;//事務,在這里代表一種功能,但如果要插入多個功能,就不能這么寫了,看下一個案例,可以把他們加入在一個攔截器鏈表里 public MyInterceptor(Object target, Transaction transaction) { super(); this.target = target; this.transaction = transaction; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String methodName = method.getName(); if("savePerson".equals(methodName) || "updatePerson".equals(methodName) || "deletePerson".equals(methodName)){ this.transaction.beginTransaction();//開啟 事務 method.invoke(target);//調用目標方法 this.transaction.commit();//事務的提交 }else{ method.invoke(target); } return null; } }package com.itheima.spring.jdkproxy;import java.lang.reflect.Proxy;import org.junit.Test;/** * 1、攔截器的invoke方法是在是什么時候執行的? * 當在客戶端,代理對象調用方法的時候,進入到了攔截器的invoke方法 * 2、代理對象的方法體的內容是什么? * 攔截器的invoke方法的內容就是代理對象的方法的內容 * 3、攔截器中的invoke方法的參數method是誰在什么時候傳遞過來的? * 代理對象調用方法的時候,進入了攔截器中的invoke方法,所以invoke * 方法中的參數method就是代理對象調用的方法 * @author xx */public class JDKProxyTest { /** * 1、創建一個目標類 * 2、創建一個事務 * 3、創建一個攔截器 * 4、動態生成一個代理對象 */ @Test public void test() { Object target = new PersonDaoImpl(); Transaction transaction = new Transaction(); MyInterceptor interceptor = new MyInterceptor(target,transaction); /* *1、目標類的加載器 *2、目標類的所有的接口 *3、攔截器 */ PersonDao personDao = (PersonDao) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), interceptor); personDao.savePerson(); }}思考動態代理是怎么生成的?
 jdk的動態代理不用寫代理方法,它是由java虛擬機實現的,因為JDK生成的最終真正的代理類,它繼承自Proxy并實現了我們定義的PersonDao接口,在實現PersonDao接口方法的內部,通過反射調用了InvocationHandlerImpl的invoke方法。
jdk動態代理比靜態代理先進(不同)在哪?有什么優勢?
①解決代碼重用的問題
②解耦,代碼靈活性高,調用目標代碼時,會在方法“運行時”動態的加入
以上的JdkProxy代碼有什么缺點?
①攔截器中除了能調用目標對象的目標方法以外,功能是比較單一,這個例子只能處理事務(見下面代碼)
②攔截器中invoke方法的if語句(切入點)是不靠譜的,因為一旦方法多了要寫很多(可用正則表達式)
3、另一種改進的JDK動態代理模式package com.itheima.spring.jdkproxy;
/** * 給日志、事務等做了一個抽象,而這個抽象就是Interceptor * @author xx * */public interface Interceptor { /* * 除了目標對象的目標方法之外,其他任何的功能,比如事務、日志等都寫在interceptor里面 */ public void interceptor();}package com.itheima.spring.jdkproxy;/** * Spring的實現比這復雜,用的責任鏈模式 * @author xx * */public class Transaction implements Interceptor{ @Override public void interceptor() { System.out.println("transaction"); }}package com.itheima.spring.jdkproxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.util.List;/** * 攔截器: * 1、目標類導入進來 * 2、事務導入進來 * 3、invoke完成 * ①開啟事務 * ②調用目標對象的方法 * ③事務提交 * @author xx * */public class MyInterceptor implements InvocationHandler{ private Object target; //目標類 List<Interceptor> interceptors; public MyInterceptor(Object target, List<Interceptor> interceptors) { super(); this.target = target; this.interceptors = interceptors; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String methodName = method.getName(); if("savePerson".equals(methodName) || "updatePerson".equals(methodName) || "deletePerson".equals(methodName)){ for(Interceptor interceptor: interceptors){ interceptor.interceptor(); } } method.invoke(target); return null; }} package com.itheima.spring.jdkproxy;import java.lang.reflect.Proxy;import java.util.ArrayList;import java.util.List;import org.junit.Test;/** * 1、攔截器的invoke方法是在是什么時候執行的? * 當在客戶端,代理對象調用方法的時候,進入到了攔截器的invoke方法 * 2、代理對象的方法體的內容是什么? * 攔截器的invoke方法的內容就是代理對象的方法的內容 * 3、攔截器中的invoke方法的參數method是誰在什么時候傳遞過來的? * 代理對象調用方法的時候,進入了攔截器中的invoke方法,所以invoke * 方法中的參數method就是代理對象調用的方法 * @author xx */public class JDKProxyTest { /** * 1、創建一個目標類 * 2、創建一個事務 * 3、創建一個攔截器 * 4、動態生成一個代理對象 */ @Test public void test() { Object target = new PersonDaoImpl(); Transaction transaction = new Transaction(); List<Interceptor> interceptors = new ArrayList<Interceptor>(); interceptors.add(transaction); MyInterceptor interceptor = new MyInterceptor(target,interceptors); /* *1、目標類的加載器 *2、目標類的所有的接口 *3、攔截器 */ PersonDao personDao = (PersonDao) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), interceptor); personDao.savePerson(); }}思考改進的代碼解決了什么問題?
解決了之前代碼的缺點一的問題

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 湟源县| 安福县| 南宁市| 石家庄市| 察雅县| 宜黄县| 思茅市| 灵宝市| 曲麻莱县| 双流县| 麻阳| 奉新县| 建阳市| 三原县| 敦化市| 浮梁县| 文登市| 乐陵市| 阿拉尔市| 库尔勒市| 天水市| 西昌市| 老河口市| 永嘉县| 泽普县| 沾化县| 陈巴尔虎旗| 民县| 陆河县| 翁牛特旗| 武宁县| 日喀则市| 红桥区| 洛南县| 乐东| 百色市| 万年县| 平顺县| 揭西县| 晋城| 崇仁县|