乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      細(xì)說代理模式

       貪挽懶月 2022-06-20 發(fā)布于廣東

      代理模式,大家應(yīng)該都不陌生,很多框架底層都用了代理模式,像spring、mybatis等。雖然大家都聽說過代理模式,但是可能也并不是那么地了解,本文將說一下常用的代理模式。

      一、代理模式介紹

      代理模式其實(shí)就是找替身,要去辦一件事兒,自己不去,找人代替你去,這就是代理模式。在程序中就是,為對(duì)象提供一個(gè)替身,控制替身去訪問目標(biāo)對(duì)象,這樣做的好處是,除了目標(biāo)對(duì)象能提供的功能外,還可以讓替身多做一些活,即可以擴(kuò)展目標(biāo)對(duì)象的功能。被代理的可以是遠(yuǎn)程對(duì)象、創(chuàng)建時(shí)開銷很大的對(duì)象或者需要安全控制的對(duì)象。

      代理模式主要分為以下三種:

      • 靜態(tài)代理
      • 動(dòng)態(tài)代理(又叫JDK代理、接口代理)
      • cglib代理(也屬于動(dòng)態(tài)代理的范疇)

      二、靜態(tài)代理

      「1、靜態(tài)代理介紹:」

      使用靜態(tài)代理的時(shí)候,需要定義接口或者父類,被代理的對(duì)象和代理對(duì)象需要一起實(shí)現(xiàn)相同的接口或者繼承相同的父類。

      「2、應(yīng)用實(shí)例:」

      • 定義一個(gè)接口:TeacherDao
      • 定義被代理的對(duì)象:TeacherDaoImpl,需要實(shí)現(xiàn)TeacherDao
      • 定義代理對(duì)象:TeacherDaoProxy,也需要實(shí)現(xiàn)TeacherDao
      • 要調(diào)用TeacherDaoImpl方法時(shí),需要先創(chuàng)建TeacherDaoProxy對(duì)象,然后創(chuàng)建TeacherDaoImpl對(duì)象,將TeacherDaoImpl對(duì)象交給TeacherDaoProxy對(duì)象,再調(diào)相關(guān)方法

      代碼實(shí)現(xiàn):

      • TeacherDao.java:
      public interface TeacherDao {
          void teach();
      }
      • TeacherDaoImpl.java:
      public class TeacherDaoImpl implements TeacherDao {
          @Override
          public void teach() {
              System.out.println("今天又是沒妹子的一天(ノへ ̄、)");
          }
      }
      • TeacherDaoProxy.java:
      public class TeacherDaoProxy implements TeacherDao {
          
          private TeacherDao target; // 被代理的對(duì)象
          
          public TeacherDaoProxy(TeacherDao target){
              this.target = target;
          }
          
          @Override
          public void teach() {
              System.out.println("代理開始");
              // 這里可以寫一些額外的邏輯,以達(dá)到擴(kuò)展被代理對(duì)象的目的,相當(dāng)于spring的前置通知
              target.teach();
              // 這里也可以寫一些額外的邏輯,以達(dá)到擴(kuò)展被代理對(duì)象的目的,相當(dāng)于spring的后置通知
              System.out.println("代理結(jié)束");
          }
      }
      • Client.java:調(diào)用代理對(duì)象
      public class Client {

          public static void main(String[] args){
              // 創(chuàng)建被代理的對(duì)象
              TeacherDao target = new TeacherDaoImpl();
              // 創(chuàng)建代理對(duì)象
              TeacherDaoProxy proxy = new TeacherDaoProxy(target);
              // 通過代理對(duì)象調(diào)用方法
              proxy.teach();
          }
      }

      「3、靜態(tài)代理的優(yōu)缺點(diǎn):」

      • 優(yōu)點(diǎn):可以在不修改被代理對(duì)象的前提下擴(kuò)展被代理的對(duì)象,做一些增強(qiáng)
      • 缺點(diǎn):需要實(shí)現(xiàn)相同的接口或者繼承相同的父類,所以代理類會(huì)很多,而且如果接口或者父類有改動(dòng),代理對(duì)象和被代理對(duì)象都需要維護(hù)

      三、動(dòng)態(tài)代理(JDK代理)

      「1、動(dòng)態(tài)代理介紹:」

      代理對(duì)象不要實(shí)現(xiàn)接口,但是被代理對(duì)象還是需要實(shí)現(xiàn)接口的。動(dòng)態(tài)代理對(duì)象的生成,利用的是JDK的API,反射包下的Proxy類,動(dòng)態(tài)地在內(nèi)存中構(gòu)建代理對(duì)象。

      「2、java.lang.reflect.Proxy:」

      這個(gè)類有一個(gè)newProxyInstance方法,該方法接收三個(gè)參數(shù),如下:

      static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)

      「3、應(yīng)用實(shí)例:」

      • 定義一個(gè)接口:TeacherDao
      • 定義被代理的對(duì)象:TeacherDaoImpl,需要實(shí)現(xiàn)TeacherDao
      • 定義一個(gè)代理工廠ProxyFactory,有一個(gè)getProxyInstance方法,需要傳入被代理的對(duì)象,然后返回代理對(duì)象實(shí)例,通過代理對(duì)象調(diào)用被代理對(duì)象的方法

      代碼實(shí)現(xiàn):

      • TeacherDao.java:
      public interface TeacherDao {
          void teach();
      }
      • TeacherDaoImpl.java:
      public class TeacherDaoImpl implements TeacherDao {
          @Override
          public void teach() {
              System.out.println("今天又是沒妹子的一天(ノへ ̄、)");
          }
      }
      • ProxyFactory.java
      public class ProxyFactory {

          private Object target; // 被代理的對(duì)象

          public ProxyFactory(Object target){
              this.target = target;
          }

          // 給被代理的對(duì)象生成一個(gè)代理對(duì)象
          public Object getProxyInstance(){
              // 參數(shù)1:指定被代理對(duì)象的類加載器
              // 參數(shù)2:被代理對(duì)象實(shí)現(xiàn)的接口類型
              // 參數(shù)3:事件處理,執(zhí)行被代理對(duì)象的方法
              return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
                  @Override
                  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                      System.out.println("JDK代理開始");
                      // 調(diào)用方法,args的方法的參數(shù)
                      Object returnValue = method.invoke(target, args);
                      System.out.println("JDK代理結(jié)束");
                      // 將執(zhí)行結(jié)果return
                      return returnValue;
                  }
              });
          }
      }
      • Client.java:通過代理調(diào)用方法
      public class Client {

          public static void main(String[] args){
              // 創(chuàng)建被代理的對(duì)象
              TeacherDao target = new TeacherDaoImpl();
              // 創(chuàng)建代理對(duì)象
              TeacherDao proxy = (TeacherDao) new ProxyFactory(target).getProxyInstance();
              // 通過代理對(duì)象調(diào)用被代理對(duì)象的方法
              proxy.teach();
          }
      }

      四、cglib代理

      「1、cglib代理介紹:」

      靜態(tài)代理和動(dòng)態(tài)代理,被代理的對(duì)象,都需要實(shí)現(xiàn)接口,如果一個(gè)類沒實(shí)現(xiàn)任何接口的,那就要用cglib代理了。cglib代理也叫子類代理,它會(huì)在內(nèi)存中構(gòu)建一個(gè)子類對(duì)象,從而實(shí)現(xiàn)對(duì)被代理對(duì)象的擴(kuò)展。cglib代理底層是通過一個(gè)叫ASM的字節(jié)碼處理框架來轉(zhuǎn)換字節(jié)碼并生成新的類從而實(shí)現(xiàn)代理的。被代理的類不能為final,否則會(huì)報(bào)錯(cuò)。被代理對(duì)象的方法如果是final/static,就不會(huì)被攔截,即不會(huì)執(zhí)行被代理對(duì)象額外的業(yè)務(wù)方法。

      「2、應(yīng)用實(shí)例:」

      • 首先要添加cglib相關(guān)依賴:
      <dependency>
           <groupId>cglib</groupId>
           <artifactId>cglib</artifactId>
           <version>3.3.0</version>
      </dependency>
      • TeacherDaoImpl.java:
      public class TeacherDaoImpl implements TeacherDao {
          @Override
          public void teach() {
              System.out.println("今天又是沒妹子的一天(ノへ ̄、)");
          }
      }
      • CglibProxyFactory.java:
      // 需要實(shí)現(xiàn)MethodInterceptor并重寫其方法
      public class CglibProxyFactory implements MethodInterceptor {

          private Object target;

          public CglibProxyFactory(Object target){
              this.target = target;
          }

          /**
           * 返回target的代理對(duì)象
           * @return
           */
          public Object getProxyInstance(){
              // 1. 創(chuàng)建工具類
              Enhancer enhancer = new Enhancer();
              // 2. 設(shè)置父類
              enhancer.setSuperclass(target.getClass());
              // 3. 設(shè)置回調(diào)函數(shù)
              enhancer.setCallback(this);
              // 4. 創(chuàng)建子類對(duì)象,即代理對(duì)象
              return enhancer.create();
          }
          @Override
          public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
              System.out.println("CGLIB代理開始");
              Object returnValue = method.invoke(target, args);
              System.out.println("CGLIB代理結(jié)束");
              return returnValue;
          }
      }
      • Client.java:通過代理調(diào)用方法
      public class Client {

          public static void main(String[] args){
              // 創(chuàng)建被代理的對(duì)象
              TeacherDaoImpl target = new TeacherDaoImpl();
              // 獲取代理對(duì)象,并將被代理對(duì)象傳給代理對(duì)象
              TeacherDaoImpl proxy = (TeacherDaoImpl) new CglibProxyFactory(target).getProxyInstance();
              // 執(zhí)行方法,觸發(fā)intecept方法,從而實(shí)現(xiàn)執(zhí)行被代理對(duì)象的方法
              proxy.teach();
          }
      }
      -java開發(fā)那些事-

        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多