静态代理、JDK动态代理和CGLIB动态代理之间的区别?

1. 静态代理

特点:代理类实现和被代理类相同的接口,并使用构造方法传递被代理类对象的引用,重新接口中的方法

需要共同的接口:

    public interface IUserService {

        //登录
        public void login(String username,String password);
        //注册
        public void regist();
    }

具体的实现类:

public class UserServiceImpl implements IUserService {

    @Override
    public void login(String username, String password) {
        System.out.println("登录功能.......");
    }

    @Override
    public void regist() {
        System.out.println("注册功能.......");
    }

}

代理类:

public class Proxy implements IUserService {

    //得到目标对象
    private IUserService target;

    //使用构造方法传递目标对象
    public Proxy(IUserService target) {
        super();
        this.target = target;
    }

    @Override
    public void login(String username, String password) {
        System.out.println("增强方法前");
        target.login(username, password);
        System.out.println("增强方法后");
    }

    @Override
    public void regist() {
        System.out.println("增强方法前");
        target.regist();
        System.out.println("增强方法后");
    }

    public static void main(String[] args) {
        //创建具体的实现类对象
        IUserService userService = new UserServiceImpl();
        //创建代理对象,并通过构造传递具体对象
        Proxy proxy = new Proxy(userService);
        //执行代理对象的方法
        proxy.login("tony", "123456");
    }

}

执行结果:

增强方法前
登录功能.......
增强方法后

总结:

从上面的代码中可以看出静态代理类,将代码写死了,如果需要这个代理类代理多个类那么就需要为每个类编写代码,这样做不利于程序的扩展,现实中一般不会这么做的

2. JDK动态代理

下面使用JDK原生的动态代理的方式实现代码的增强:

public class JDKProxyFactory implements InvocationHandler {

    private Object target;

    public JDKProxyFactory(Object target) {
        super();
        this.target = target;
    }

    // 创建代理对象
    public Object createProxy() {
        // 1.得到目标对象的类加载器
        ClassLoader classLoader = target.getClass().getClassLoader();
        // 2.得到目标对象的实现接口
        Class<?>[] interfaces = target.getClass().getInterfaces();
        // 3.第三个参数需要一个实现invocationHandler接口的对象
        Object newProxyInstance = Proxy.newProxyInstance(classLoader, interfaces, this);
        return newProxyInstance;
    }

    @Override
    // 第一个参数:代理对象.一般不使用;第二个参数:需要增强的方法;第三个参数:方法中的参数
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 增强前
        System.out.println("这是增强方法前......");
        Object invoke = method.invoke(target, args);
        // 增强后
        System.out.println("这是增强方法后......");
        return invoke;
    }

    public static void main(String[] args) {
        // 1.创建对象
        UserServiceImpl userService = new UserServiceImpl();
        // 2.创建代理对象
        JDKProxyFactory proxy = new JDKProxyFactory(userService);
        // 3.调用代理对象的增强方法,得到增强后的对象
        IUserService createProxy = (IUserService) proxy.createProxy();
        createProxy.regist();
    }
}

总结:

JDK动态代理类实现了InvocationHandler接口。在重写的invoke方法中可以看出,JDK动态代理的基础是反射(method.invoke(对象,参数))Proxy.newProxyInstance(),这个方法,字面上的意思是新建一个代理类的实例,这一点就和静态代理不同了。里面的参数有三个 类加载器、所有的接口,得到InvocationHandler接口的子类实例。

这就是JDK动态代理,该代理有以下几种特点:

  1、Interface:对于JDK Proxy,业务类是需要一个Interface的,这是一个缺陷;

  2、Proxy:Proxy类是动态产生的,这个类在调用Proxy.newProxyInstance()方法之后,产生一个Proxy类的实力。实际上,这个Proxy类也是存在的,不仅仅是类的实例,这个Proxy类可以保存在硬盘上;

  3、Method:对于业务委托类的每个方法,现在Proxy类里面都不用静态显示出来

  4、InvocationHandler:这个类在业务委托类执行时,会先调用invoke方法。invoke方法在执行想要的代理操作,可以实现对业务方法的再包装。

3. CGLIB动态代理

CGLIB(Code Generation Library)是一个开源项目,是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java类与实现Java接口。CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类.如果你要单独使用CGLIB,那么需要导入cglib的jar包还需要一个asm相关jar包,但是spring框架的spring-core.jar包中已经集成了cglib与asm.

CGLib是针对类来实现代理的,他的原理是对指定的目标生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理

注意:jdk的动态代理只可以为接口去完成操作,而cglib它可以为没有实现接口的类去做代理,也可以为实现接口的类去做代理。

public class CglibProxyFactory implements MethodInterceptor {

    //得到目标对象
    private Object target;

    //使用构造方法传递目标对象
    public CglibProxyFactory(Object target) {
        super();
        this.target = target;
    }

    //创建代理对象
    public Object createProxy(){
        //1.创建Enhancer
        Enhancer enhancer = new Enhancer();
        //2.传递目标对象的class
        enhancer.setSuperclass(target.getClass());
        //3.设置回调操作
        enhancer.setCallback(this);

        return enhancer.create();
    }

    @Override
    //参数一:代理对象;参数二:需要增强的方法;参数三:需要增强方法的参数;参数四:需要增强的方法的代理
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        // 增强前
        System.out.println("这是增强方法前......");
        Object invoke = methodProxy.invoke(target, args);
        // 增强后
        System.out.println("这是增强方法后......");
        return invoke;
    }

    public static void main(String[] args) {
        // 1.创建对象
        UserServiceImpl userService = new UserServiceImpl();
        // 2.创建代理对象
        CglibProxyFactory proxy = new CglibProxyFactory(userService);
        // 3.调用代理对象的增强方法,得到增强后的对象
        IUserService createProxy = (IUserService) proxy.createProxy();
        createProxy.regist();
    }
}

猜你喜欢

转载自blog.csdn.net/happy_write/article/details/81235096
今日推荐