Java代理 - Proxy

1.理论

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

代理也称“委托”,分为静态代理和动态代理,代理模式也是常用的设计模式之一,具有方法增强、高扩展性的设计优势。

2.分类

静态代理:编译期已经确定被代理的对象和代理类;实现简单且不侵入原代码,当接口改动时,需要同时修改代理类,不易维护。

动态代理:在运行期间才确定被代理的对象,并动态生成一个代理类;对比静态代理,对代理类统一处理,而不用修改每个代理类。

  • JDK动态代理(接口代理):通过JAVA反射来创建代理类(反射机制在生成类的过程中比较高效)。被代理类和代理类实现同样的接口,实现 InvokecationHandler接口。
  • CGLIB动态代理(子类代理):通过ASM编辑字节码文件来生成一个代理类(ASM在生成类之后的相关执行过程中比较高效)。生成的代理类继承被代理类,实现 MethodInterceptor接口。

3.实现

静态代理:

// 接口
public interface StaticProxyInterface {
    void work();
}
// 目标对象:要被代理的类实现接口
public class TargetObject implements StaticProxyInterface{
    @Override
    public void work() {
        System.out.println("开始搬砖...");
    }
}
// 代理类
public class StaticProxyObject implements StaticProxyInterface{

    private TargetObject targetObject;
    // 通过构造方法注入目标真实对象
    public StaticProxyObject(TargetObject targetObject) {
        this.targetObject = targetObject;
    }

    @Override
    public void work() {
        clock();
        targetObject.work();
    }
    //增强方法
    private void clock(){
        System.out.println("打卡...");
    }
}
// 测试
public static void main(String[] args) {
    StaticProxyInterface staticProxyInterface = new StaticProxyObject(new TargetObject());
   System.out.println(staticProxyInterface.getClass()); staticProxyInterface.work(); }
class com.yue.proxy.StaticProxyObject 打卡... 开始搬砖...

 JDK动态代理:

// 接口
public interface SubjectInterface {
    void work();
}
// 目标对象:要被代理的类实现接口
public class TargetObject implements SubjectInterface{
    @Override
    public void work() {
        System.out.println("开始搬砖...");
    }
}
// JDK动态代理类
public class JDKProxyObject implements InvocationHandler {

    private SubjectInterface target;
    // 通过构造方法注入目标真实对象
    public JDKProxyObject(SubjectInterface target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        clock();
        return method.invoke(target, args);
    }

    private void clock(){
        System.out.println("打卡...");
    }
}
// 测试
public static void main(String[] args) {
    SubjectInterface subjectInterface = new TargetObject();
    JDKProxyObject jdkProxyObject = new JDKProxyObject(subjectInterface);
    SubjectInterface subject = (SubjectInterface) Proxy.newProxyInstance(jdkProxyObject.getClass().getClassLoader(),subjectInterface.getClass().getInterfaces(),jdkProxyObject);
    System.out.println(subject.getClass());
    subject.work();
}
// 输出内容
class com.sun.proxy.$Proxy0
打卡...
开始搬砖...

Cglib动态代理

// 目标对象:要被代理的类
public class TargetObject {
    public void work() {
        System.out.println("开始搬砖...");
    }
}
// 使用 Cglib 代理
public class CglibProxyObject implements MethodInterceptor {

    public Object getProxyInstance(Class clazz){
        // 创建一个工具类
        Enhancer enhancer = new Enhancer();
        // 设置父类
        enhancer.setSuperclass(clazz);
        // 设置回调函数
        enhancer.setCallback(this);
        // 创建子类对象,即代理对象
        return enhancer.create();
    }

    // 拦截方法
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        clock();
        return methodProxy.invokeSuper(o, objects);
    }

    private void clock(){
        System.out.println("打卡...");
    }
}

public static void main(String[] args) {
    TargetObject cglibProxy = (TargetObject)new CglibProxyObject().getProxyInstance(TargetObject.class);
    System.out.println(cglibProxy.getClass());
    cglibProxy.work();
}
// 输出内容
class com.yue.proxy.TargetObject$$EnhancerByCGLIB$$8e8022b6
打卡...
开始搬砖...

 

posted @ 2020-12-18 10:55  柒月丶  阅读(300)  评论(0)    收藏  举报