java的三种代理

java的三种代理

代理

静态代理

  1. 编写需要目标对象实现的接口
/**
 * 接口
 */
public interface Action {

    /**
     * dosomething
     */
    void doSomething();
}
  1. 编写目标类,实现接口
/**
 * @author earthchen
 * @date 2018/8/10
 **/
public class RealObject implements Action {

    @Override
    public void doSomething() {
        System.out.println(this.getClass().getName()+"dosomething....");
    }
}
  1. 编写静态代理类,也需要实现该接口
/**
 * 代理类
 *
 * @author earthchen
 * @date 2018/8/10
 **/
public class Proxy implements Action {

    private Action realObject;

    public Proxy(Action realObject) {
        this.realObject = realObject;
    }

    @Override
    public void doSomething() {
        System.out.println("proxy do");
        realObject.doSomething();
    }
}

需要维护一个接口的对象

  1. 编写main方法进行测试
public class Main {

    public static void main(String[] args) {
        Action action = new RealObject();
        Proxy proxy = new Proxy(action);
        proxy.doSomething();
    }
}

优缺点

这种代理方式需要代理对象和目标对象实现一样的接口。

  1. 优点:可以在不修改目标对象的前提下扩展目标对象的功能。
  2. 缺点:
  • 冗余。由于代理对象要实现与目标对象一致的接口,会产生过多的代理类。
  • 不易维护。一旦接口增加方法,目标对象与代理对象都要进行修改。

jdk动态代理

  1. 和静态代理一样,编写一个接口
/**
 * @author earthchen
 * @date 2018/8/10
 **/
public interface Action {

    void doSomeThing();

}
  1. 编写多个目标类,实现接口
/**
 * @author earthchen
 * @date 2018/8/10
 **/
public class RealObject1 implements Action {

    @Override
    public void doSomeThing() {
        System.out.println(this.getClass().getName()+"do someThing...");
    }
}

/**
 * @author earthchen
 * @date 2018/8/10
 **/
public class RealObject2 implements Action {

    @Override
    public void doSomeThing() {
        System.out.println(this.getClass().getName()+"do someThing...");
    }
}
  1. 编写动态代理类,
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * @author earthchen
 * @date 2018/8/10
 **/
public class DynamicProxyHandler implements InvocationHandler {

    private Action testAction;

    public DynamicProxyHandler(Action testAction) {
        this.testAction = testAction;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //代理扩展逻辑
        System.out.println("proxy do");

        return method.invoke(testAction, args);
    }
}
  1. 编写main方法进行测试
public class Main {

    public static void main(String[] args) {
        RealObject1 realObject1 = new RealObject1();
        Action proxy1 = (Action) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),
                new Class[]{Action.class}, new DynamicProxyHandler(realObject1));
        proxy1.doSomeThing();


        RealObject2 realObject2 = new RealObject2();
        Action proxy2 = (Action) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),
                new Class[]{Action.class}, new DynamicProxyHandler(realObject2));
        proxy2.doSomeThing();
    }
}

静态代理与动态代理的区别

  • 静态代理在编译时就已经实现,编译完成后代理类是一个实际的class文件
  • 动态代理是在运行时动态生成的,即编译完成后没有实际的class文件,而是在运行时动态生成类字节码,并加载到JVM中

特点:

动态代理对象不需要实现接口,但是要求目标对象必须实现接口,否则不能使用动态代理。

cglib代理

  1. 在pom.xml中引入cglib的依赖
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.2.5</version>
</dependency>
  1. 直接编写需要代理的目标类
public class RealObject {

    public void doSomeThing(){
        System.out.println(this.getClass().getName()+"do someThing...");
    }
}
  1. 编写cglib代理类
import java.lang.reflect.Method;

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

/**
 * @author earthchen
 * @date 2018/8/10
 **/
public class CglibProxy implements MethodInterceptor {

    private Object target;

    public CglibProxy(Object object) {
        this.target = object;
    }

    /**
     * 为目标对象生成代理对象
     *
     * @return
     */
    public Object getProxyInstance() {
        //工具类
        Enhancer en = new Enhancer();
        //设置父类
        en.setSuperclass(target.getClass());
        //设置回调函数
        en.setCallback(this);
        //创建子类对象代理
        return en.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("before do someThing.....");
        // 执行目标对象的方法
        Object returnValue = method.invoke(target, objects);
        System.out.println("after do someThing....");
        return returnValue;
    }
}

cglib与动态代理的区别

  • 使用动态代理的对象必须实现一个或多个接口
  • 使用cglib代理的对象则无需实现接口,达到代理类无侵入。

cglib特点

  • JDK的动态代理有一个限制,就是使用动态代理的对象必须实现一个或多个接口。 如果想代理没有实现接口的类,就可以使用CGLIB实现
  • CGLIB是一个强大的高性能的代码生成包,它可以在运行期扩展Java类与实现Java接口。它广泛的被许多AOP的框架使用,例如Spring AOP和dynaop,为他们提供方法的interception(拦截)
  • CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。不鼓励直接使用ASM,因为它需要你对JVM内部结构包括class文件的格式和指令集都很熟悉

总结

  1. 静态代理实现较简单,只要代理对象对目标对象进行包装,即可实现增强功能,但静态代理只能为一个目标对象服务,如果目标对象过多,则会产生很多代理类。
  2. JDK动态代理需要目标对象实现业务接口,代理类只需实现InvocationHandler接口。
  3. 静态代理在编译时产生class字节码文件,可以直接使用,效率高。
  4. 动态代理必须实现InvocationHandler接口,通过反射代理方法,比较消耗系统性能,但可以减少代理类的数量,使用更灵活。
  5. cglib代理无需实现接口,通过生成类字节码实现代理,比反射稍快,不存在性能问题,但cglib会继承目标对象,需要重写方法,所以目标对象不能为final类。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Java的三种代理模式

    代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即...

    Java团长
  • 快速理解Java的三种代理模式

    代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式,即通过代理对象访问目标对象。这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即...

    全菜工程师小辉
  • 一篇文章让你弄懂Java的三种代理

    代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即...

    Java编程指南
  • 详解 Java 中的三种代理模式

    代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即...

    Java技术栈
  • 详解 Java 中的三种代理模式

    来 源:http://cnblogs.com/cenyu/p/6289209.html

    一个优秀的废人
  • java 处理xml的三种技术

    最初,XML 语言仅仅是意图用来作为 HTML 语言的替代品而出现的,但是随着该语言的不断发展和完善,人们越来越发现它所具有的优点:例如标记语言可扩...

    java达人
  • Java代码复用的三种常用方式:继承、组合和代理

    复用代码是Java众多引人注目的功能之一。这句话很通顺,没什么问题,但问题在于很多人并不清楚“复用”是什么。就好像我说“沉默王二是一个不止会写代码的程序员”,唉...

    沉默王二
  • Jmeter:Beanshell调用java代码的三种方式

    props.get("START.YMD"); //获取属性 START.YMD 的值(脚本启动日期)

    java乐园
  • 深入理解Java的三种工厂模式

    简单工厂的定义:提供一个创建对象实例的功能,而无须关心其具体实现。被创建实例的类型可以是接口、抽象类,也可以是具体的类

    芋道源码

扫码关注云+社区

领取腾讯云代金券