设计模式---JDK动态代理和CGLIB代理

Posted binghuazhang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式---JDK动态代理和CGLIB代理相关的知识,希望对你有一定的参考价值。

Cglig代理设计模式

/*测试类*/

package cglibProxy;

import org.junit.Test;

public class TestCglib {

  @Test
  public void test1(){
    CglibProxy cglibProxy=new CglibProxy();
    UserServiceImpl userServiceImpl = (UserServiceImpl)cglibProxy.createProxyInstance(new UserServiceImpl());
    userServiceImpl.addUser();
  }
}

 

/*代理类*/

package cglibProxy;

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

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class CglibProxy implements MethodInterceptor{

    //1.声明一个全局变量,被代理对象
    private Object target;

    //2.创建代理对象
    //参数是被代理对象
    public Object createProxyInstance(Object target){
    //赋值被代理对象
    this.target=target;
    Enhancer enhancer = new Enhancer();
    //设置代理对象的父类
    enhancer.setSuperclass(target.getClass());

    //设置回调函数
    //Callback是MethodInterceptor的父接口
    enhancer.setCallback(this);
    //返回创建出来的代理对象
    return enhancer.create();


  }

    //加工
    public Object intercept(Object proxy, Method method, Object[] arg,
      MethodProxy proxyMethod) throws Throwable {
      // TODO Auto-generated method stub


      //加工
      security();

    return proxyMethod.invoke(target, arg);

    }


    public void security(){
      System.out.println("进行权限控制");

    }
 }

 

/*需要被代理对象*/

package cglibProxy;

public class UserServiceImpl{

  public void addUser() {

    System.out.println("增加了用户");
    // TODO Auto-generated method stub

  }

  public void deleteUser() {

    System.out.println("删除了用户");
    // TODO Auto-generated method stub

  }

  public void alterUser() {

    System.out.println("修改了用户");
    // TODO Auto-generated method stub

  }

  public void findUser() {
    System.out.println("查询了用户");
    // TODO Auto-generated method stub

  }

  public void security(){
    System.out.println("进行了权限控制111");

  }

}

 

JDK动态代理设计模式

/*接口*/

package jdkProxy;

public interface IUserService {
  public void addUser();
  public void deleteUser();
  public void alterUser();
  public void findUser();
}

 

/*代理类*/

package jdkProxy;

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

//整个类是切面类
public class JdkProxy implements InvocationHandler {

  //创建全局变量,被代理对象
  private Object target;

  //创建代理对象
  public Object createProxyInstance(Object target){
    //获取目标对象并赋值
    this.target=target;

    //根据目标对象创建对应的代理对象
    //三个参数,1.被代理对象的类加载器,2,被代理对象的所有接口,3,类型为InvocationHandler的对象,在本类中只有JdkProxy了
    //想要拿到类加载器首先拿到字节码,第三个参数this是指JdkProxy
    return Proxy.newProxyInstance(target.getClass().getClassLoader(),
    target.getClass().getInterfaces(), this);
  }


  //invoke这个方法是InvocationHandler的方法,实现需要重写
  //加工被代理对象
  //1.第一个参数是 刚创建的代理对象
  //2.第二个参数是需要被加工的方法,真实方法
  //3.第三个参数,需要被加工的方法的参数

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

    //加工
    security();

    //执行被代理对象的方法,最终是由被代理对象的方法
    return method.invoke(target, args);
  }

  //通知(增强)方法
  public void security(){
    System.out.println("进行权限控制");

  }

}

 

/*测试类*/

package jdkProxy;

import org.junit.Test;

public class TestJdkProxy {

  @Test
  public void tes1(){
    // IUserService userService=new UserServiceImpl();
    // userService.addUser();

    //创建代理对象,jdkProxy
    JdkProxy proxy=new JdkProxy();
    //执行创建代理对象的方法
    //参数就是被代理的对象
    //被代理对象要和代理对象接口要一致,要求被代理对象一定要实现接口

    //织入, weaver,就是创建一个代理对象,并调用被代理方法
   IUserService userService =(IUserService) proxy.createProxyInstance(new UserServiceImpl());
    userService.addUser();
  }
}

 

/*被代理对象*/

package jdkProxy;

public class UserServiceImpl implements IUserService {

  public void addUser() {

    System.out.println("增加了用户");
    // TODO Auto-generated method stub

  }

  public void deleteUser() {

    System.out.println("删除了用户");
    // TODO Auto-generated method stub

  }

  public void alterUser() {

    System.out.println("修改了用户");
    // TODO Auto-generated method stub

  }

  public void findUser() {
    System.out.println("查询了用户");
    // TODO Auto-generated method stub

  }

  public void security(){
    System.out.println("权限控制");

  }

}

动态代理:JDK动态代理和CGLIB代理的区别

代理模式:代理类和被代理类实现共同的接口(或继承),代理类中存有指向被代理类的索引,实际执行时通过调用代理类的方法、实际执行的是被代理类的方法。

技术图片

而AOP,是通过动态代理实现的。

一、简单来说:

  JDK动态代理只能对实现了接口的类生成代理,而不能针对类

  CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法(继承)

二、Spring在选择用JDK还是CGLiB的依据:

   (1)当Bean实现接口时,Spring就会用JDK的动态代理

   (2)当Bean没有实现接口时,Spring使用CGlib是实现

   (3)可以强制使用CGlib(在spring配置中加入<aop:aspectj-autoproxy proxy-target-class="true"/>)

三、CGlib比JDK快?

  (1)使用CGLib实现动态代理,CGLib底层采用ASM字节码生成框架,使用字节码技术生成代理类,比使用Java反射效率要高。唯一需要注意的是,CGLib不能对声明为final的方法进行代理,因为CGLib原理是动态生成被代理类的子类。

  (2)在对JDK动态代理与CGlib动态代理的代码实验中看,1W次执行下,JDK7及8的动态代理性能比CGlib要好20%左右。

以上是关于设计模式---JDK动态代理和CGLIB代理的主要内容,如果未能解决你的问题,请参考以下文章

设计模式 结构型模式 -- 代理模式(动态代理(CGLIB动态代理)三种代理的对比(静态代理动态代理(JDK代理和CGLIB代理)优缺点使用场景))

java动态代理(JDK和cglib)

JDK动态代理和CGLIB动态代理

代理模式(静态代理jdk动态代理CGLib动态代理)

设计模式---JDK动态代理和CGLIB代理

JDK的动态代理与cglib动态代理