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();
    }

 

posted @ 2017-10-12 22:35  迷茫王子  阅读(6796)  评论(0编辑  收藏  举报