Spring筆記06(Spring AOP的底層實現動態代理)


1.代理模式readMe:

代理設計模式: 是java中常用的設計模式!

   特點:
       01.委托類和代理類有相同的接口或者共同的父類!
       02.代理類為委托類負責處理消息,並將消息轉發給委托類!
       03.委托類和代理類對象通常存在關聯關系!
          一個代理類對象與一個委托類對象關聯!
       04.代理類本身並不是真正的實現者!而是通過調用委托類的方法,
          來實現功能!


   按照代理類創建的時機,代理類分為兩種:
   01.靜態代理:由我們程序猿或者特定的工具自動生成了源代碼,
                 在程序運行之前,.class文件已經存在了!
      (serviceImpl 調用了 dao層的方法! 真正的實現是Dao)
   02.動態代理:在程序運行期間,通過反射的方式動態的創建出來!


   按照我們的使用方式:  是由共同的接口還是公共的父類?

     01.jdk動態代理 (接口)
          必須知道一個類和一個接口
           001.InvocationHandler接口只有一個方法

            public Object invoke(Object proxy, Method method, Object[] args)
                   throws Throwable;

           proxy:代理類對象
           method:被代理的方法
           args:被代理的方法的參數列表

          002.Proxy 類:
           public static Object newProxyInstance(ClassLoader loader,
                  Class<?>[] interfaces,InvocationHandler h)throws IllegalArgumentException
              loader:類加載器
              interfaces:代理類實現的所有接口
              h:InvocationHandler接口的一個實例   this當前對象
                 因為我們想使用jdk動態代理 必須是 代理類 實現 InvocationHandler!
                  它讓我們傳遞父接口 我們傳遞 自身!

     02.cglib動態代理(接口+父類)
         必須知道一個類和一個接口
           001.MethodInterceptor接口

           public Object intercept(Object obj,
              Method method,Object[] args,MethodProxy proxy) throws Throwable;

        intercept是所有攔截器執行的方法,類似於jdk動態代理中的invoke


          002. Enhancer類

           設置委托類和代理類的公共接口或者公共的父類
           public void setSuperclass(Class superclass) {
                  if (superclass != null && superclass.isInterface()) {
                      setInterfaces(new Class[]{ superclass });
                  } else if (superclass != null && superclass.equals(Object.class)) {
                      // affects choice of ClassLoader
                      this.superclass = null;
                  } else {
                      this.superclass = superclass;
                  }
              }

               代理類執行完畢 通知委托類
               public void setCallback(final Callback callback) {
                      setCallbacks(new Callback[]{ callback });
                  }


                在Enhancer類的父類AbstractClassGenerator中有一個方法
                  創建我們需要的代理類
                  protected Object create(Object key)

2.靜態代理:

01.接口代碼:

package cn.pb.dao;

/**
 * 動物類 父接口
 */
public interface Animal {
    //主業務
    void eat();
    void sleep();
}

 

02.實現類代碼:

package cn.pb.dao.impl;
/**
 * 狗狗類 實現了Animal接口
 */

import cn.pb.dao.Animal;

public class Dog implements Animal {
    public void eat() {
        System.out.println("狗狗在啃骨頭!");
    }

    public void sleep() {
        System.out.println("狗狗在午休!");
    }
}

 

03.靜態代理類:

package cn.pb.staticproxy;

import cn.pb.dao.Animal;
import cn.pb.dao.impl.Dog;

/**
 * 狗狗的靜態代理類
 */
public class AnimalStaticProxy implements Animal {

    private Dog dog;


    public void sleep() {
        System.out.println("主人在召喚");  //系統級業務
        dog.sleep();
        System.out.println("主人離開"); //系統級業務
    }

    public void eat() {
        System.out.println("主人在召喚"); //系統級業務
        dog.eat();
        System.out.println("主人離開"); //系統級業務
    }

    public Dog getDog() {
        return dog;
    }

    public void setDog(Dog dog) {
        this.dog = dog;
    }


    /**
     * 我們發現的問題
     * 01:代碼冗余
     * 02:把冗余的代碼提取成公共的方法
     * 03:有可能小貓咪也有這些方法
     * 04:提取成一個工具類中的方法
     * 05:現在有一個小貓咪 也需要執行 sleep和eat 以及系統級業務方法
     * 06:我們又得創建一個小貓咪對應的代理類
     * 07:動物有很多  ,難道需要我們創建N個代理類嗎??肯定!
     */
}

 

04.測試類代碼:

 /**
     * 靜態代理的測試方法
     */
    @Test
    public void testStaticProxy(){
        AnimalStaticProxy proxy = new AnimalStaticProxy();
        Dog dog=new Dog();
        proxy.setDog(dog);


        proxy.eat();
        System.out.println("*************");
        proxy.sleep();
    }

 

3.JDK動態代理:

01.接口代碼:

package cn.pb.dao;

/**
 * 動物類 父接口
 */
public interface Animal {
    //主業務
    void eat();
    void sleep();
}

 

02.實現類代碼:

package cn.pb.dao.impl;
/**
 * 狗狗類 實現了Animal接口
 */

import cn.pb.dao.Animal;

public class Dog implements Animal {
    public void eat() {
        System.out.println("狗狗在啃骨頭!");
    }

    public void sleep() {
        System.out.println("狗狗在午休!");
    }
}

 

03.動態代理類代碼:

package cn.pb.jdkdynamicproxy;
/**
 * JDK的動態代理類
 */

import cn.pb.dao.Animal;
import cn.pb.dao.impl.Dog;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class AnimalJdkDynamicProxy implements InvocationHandler {

    /**
     *  01.我們不確定委托類是誰?委托類的類型 是Object
     *   和委托類建立關聯關系
     */
    private Object target;


    /**
     * 02.給我一個委托類,我返回一個代理類對象
     */
    public Object createProxy(Object target){
        //根據傳遞的參數 進行對象的關聯
        this.target=target;
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(), this);
    }

    /**
     *
     * @param proxy :代理對象
     * @param method :方法名
     * @param args : 參數列表
     * @return
     */
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("主人在召喚"); //系統級業務   開始事務
        Object result= method.invoke(target,args);  // 主業務
        System.out.println("主人離開"); //系統級業務     日志處理  關閉事務
        return result;
    }


    //創建測試方法
    public static void main(String[] args) {
        AnimalJdkDynamicProxy proxy=new AnimalJdkDynamicProxy();
        Animal dog= (Animal) proxy.createProxy(new Dog());
        dog.eat();
        System.out.println("**************************");
        dog.sleep();

    }
}

 

04.測試代碼:

 @Test
    public void testJdkDynamicProxy(){
        AnimalJdkDynamicProxy proxy=new AnimalJdkDynamicProxy();
        Animal dog= (Animal) proxy.createProxy(new Dog());
        dog.eat();
        System.out.println("**************************");
        dog.sleep();
    }

 

4.cglib動態代理:

01.接口代碼:

package cn.pb.dao;

/**
 * 動物類 父接口
 */
public interface Animal {
    //主業務
    void eat();
    void sleep();
}

 

02.實現類代碼:

package cn.pb.dao.impl;
/**
 * 狗狗類 實現了Animal接口
 */

import cn.pb.dao.Animal;

public class Dog implements Animal {
    public void eat() {
        System.out.println("狗狗在啃骨頭!");
    }

    public void sleep() {
        System.out.println("狗狗在午休!");
    }
}

 

03.動態代理類代碼:

package cn.pb.cglibdynamicproxy;


/**
 * Cglib動態代理
 */
import cn.pb.dao.Animal;
import cn.pb.dao.impl.Dog;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class AnimalCglibDynamicProxy implements MethodInterceptor {

    /**
     * 在enhancer中有一個setCallBack(this)
     * 這樣就實現了代理類和委托類的關聯
     */
    private Enhancer enhancer=new Enhancer();

    /**
     *  創建代理類對象
     */
    public  Object  createProxy(Class clazz){
        //設置公共的接口或者公共的類
        enhancer.setSuperclass(clazz);
        //建立關聯關系
        enhancer.setCallback(this);
        return enhancer.create();
    }

    /**
     * 類似於我們jdk中的invoke
     */
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("主人在召喚"); //系統級業務   開始事務
        Object result= proxy.invokeSuper(obj,args);  // 主業務
        System.out.println("主人離開"); //系統級業務     日志處理  關閉事務
        return result;
    }


    //創建測試方法
    public static void main(String[] args) {
        AnimalCglibDynamicProxy proxy=new AnimalCglibDynamicProxy();
        //這里的參數可以傳三種形式01:new Dog().getClass()
        // 02:Class.forName("cn.pb.dao.impl.Dog") 03.Dog.class
        Animal dog= (Animal) proxy.createProxy(new Dog().getClass());
        dog.eat();
        System.out.println("**************************");
        dog.sleep();
    }
}

 

04.測試代碼:

  @Test
    public void testCglibDynamicProxy(){
        AnimalJdkDynamicProxy proxy=new AnimalJdkDynamicProxy();
        Animal dog= (Animal) proxy.createProxy(new Dog());
        dog.eat();
        System.out.println("**************************");
        dog.sleep();
    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM