关于JDK动态代理和cglib动态代理

在spring AOP中,由于通知类中抽取了原始对象中的公共方法,使得原始对象的方法变得不能进行完整的操作。但是我们还是想通过某个方式实现原始对象完成完整操作,我们可以通过为原始对象创建代理对象的方式达到目的,有两种方式:JDK动态代理和cglib动态代理。

一、JDK动态代理

  1、概述:针对内存中的Class对象,使用类加载器,动态为目标对象的实现接口创建代理对象。也就是说JDK代理是对对象做代理。

  2、具体实现(如下代码):

     创建一个接口及实现类     

     public interface UserDao {
      public void add();

     }

     public class UserDaoImp implements UserDao {

      @Override
      public void add() {
        System.out.println("新增用户操作");

       }

     }

    创建实现JDK动态代理的工具类

    public class JdkProxy implements InvocationHandler {

      private UserDao userDao;

      // 定义一个方法用于创建JDK代理对象
      public UserDao createProxyObject(UserDao userDao) {
        // 被代理对象作为参数传入进来
        this.userDao = userDao;
        // 获取类加载器:对谁代理,使用谁的类加载器
        ClassLoader classLoader = userDao.getClass().getClassLoader();
        // 获取被代理对象的所有实现接口
        Class<?>[] interfaces = userDao.getClass().getInterfaces();

        // 创建Handler对象,用于增强拦截,为了方便调用使用实现InvocationHandler接口的方式  

        InvocationHandler h = this;

        Object obj = Proxy.newProxyInstance(classLoader, interfaces, h);
          return (UserDao) obj;

    }

      @Override
      public Object invoke(Object proxy, Method method, Object[] args)
      throws Throwable {
        System.out.println("连接数据库");// 增强操作
        // 对原始操作进行调用(使用反射)
        method.invoke(userDao, args);
        System.out.println("关闭数据库");
        return null;
       }

      public static void main(String[] args) {
        // 1、创建一个对象
        UserDao dao = new UserDaoImp();
        // 2、为原始对象创建代理对象
        UserDao daoProxy = new JdkProxy().createProxyObject(dao);
        // 3、使用代理对象运行操作
        daoProxy.add();

      }
    }

二、cglib动态代理

  1、概述:非接口实现的对象,对于不使用接口的业务类,无法使用JDK动态代理。cglib采用底层字节码急速,可以为一个类创建子类,也就是cglib是解决无接口代理问题,

  是对类做代理。

       2、具体实现(如下代码)

  创建Person类及生成代理的方法

  public class Person {

    public void action() {
    System.out.println("Java程序员");
    }
  }

  public Person createProxyObject(Class clazz) {
    // cglib中的核心对象是Enhance,用来在内存中创建一段动态的类的字节码
    Enhancer enhancer = new Enhancer();//此时没有做继承
    // 为其指定父类,除了完成继承关系外,还将父类所有的方法反射过来,并在自己的类中创建这些方法
    enhancer.setSuperclass(clazz);
    // 进行功能的增强
    // 设置方法的调用拦截
    Callback callback = new MethodInterceptor() {
      // proxy:代理对象
      // method:被拦截的方法对象
      // args:调用函数
      // methodProxy:使用代理机制创建被代理对象的方法
      @Override
      public Object intercept(Object proxy, Method method, Object[] args,
        MethodProxy methodProxy) throws Throwable {
        // 做增强
        System.out.println("Java后端程序员还会烤肉");
        // 调用原始的操作
        Object ret = methodProxy.invokeSuper(proxy, args);
        return ret;
      }
    };
  // 设置具体的回调操作
  enhancer.setCallback(callback);
  // 创建内存中全新类的对象
  Object proxyObj = enhancer.create();
  return (Person) proxyObj;
  }

  3、小结:cglib动态代理机制其实是利用继承的思想来实现,在代码中可以看出,代理机制创建代理对象,把被代理的对象当做父类,把代理的对象

当做子类,走父类运行,走子类的实现,这体现了继承与多态的思想。

三、总结

  cglib可以对任意的类进行代理,JDKdial只能对接口实现的类进行代理。

 

posted @ 2018-12-20 22:22  程序员阿豆  阅读(161)  评论(0编辑  收藏  举报