美文网首页
java基础-代理模式

java基础-代理模式

作者: dancer4code | 来源:发表于2019-10-20 14:38 被阅读0次

1.代理模式

为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。(结构型模式)

2.优缺点

优点:

  1. 代理模式能将代理对象与真实对象被调用的目标对象分离。
  2. 一定程度上降低了系统的耦合度,扩展性好。
  3. 保护目标对象。
  4. 增强目标对象。

缺点:

  1. 代理模式会造成系统设计中类的数目的增加。
  2. 在客户端和目标对象增加一个代理对象,会造成请求处理速度变慢
  3. 增加了系统的复杂度。

3.代理模式分类

  • 静态代理
  • JDK动态代理
  • CGLIB动态代理

4.简单实现例子

静态代理

用歌手,经纪人的例子举例:


静态代理.jpg

静态代理必须实现同一个接口

代码:

public interface Sing {
    void singSongs();
}

//歌手
public class Singer implements Sing {
    @Override
    public void singSongs() {
        System.out.println("singer can sing songs");
    }
}

//经纪人
public class Agent implements Sing {
    private Sing sing = null;
    @Override
    public void singSongs() {
        sing.singSongs();
    }

    public Agent(Sing sing) {
        this.sing = sing;
        System.out.println("代理人接收到唱歌邀请");
    }
    public void before(){
        System.out.println("判断是否能去,金钱,时间安排,对歌手有没影响");
    }
    public void after(){
        System.out.println("邀请单位给出评价,相约下次合作");
    }
}

演出开始

public class Performance {
    public static void main(String[] args) {
        Singer singer = new Singer();
        Agent agent = new Agent(singer);

        agent.before();
        agent.singSongs();
        agent.after();
    }
}

result

代理人接收到唱歌邀请
判断是否能去,金钱,时间安排,对歌手有没影响
singer can sing songs
邀请单位给出评价,相约下次合作

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

JDK动态代理

JDKAgent

public class JDKAgent implements InvocationHandler {

    private Object target;

    public JDKAgent(Object target) {
        this.target = target;
    }

    public Object creatAgent(){
        // 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 {
        before();
        Object invoke = method.invoke(target, args);
        after();
        return invoke;
    }

    public void before(){
        System.out.println("判断此次演出准备工作是否到位");
    }
    public void after(){
        System.out.println("演出是否完美收官");
    }
}

测试类

public class JDKDemo {
    public static void main(String[] args) {
        Singer singer = new Singer();
        JDKAgent jdkAgent = new JDKAgent(singer);

        Sing sing = (Sing)jdkAgent.creatAgent();
        sing.singSongs();
    }
}

result

判断此次演出准备工作是否到位
singer can sing songs
演出是否完美收官

总结

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

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

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

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

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它可以为没有实现接口的类去做代理,也可以为实现接口的类去做代理

Dancer

public class Dancer {
    public void dance(){
        System.out.println("dancer can dance");
    }
}

代理类

public class CglibAgent implements MethodInterceptor {
    //得到目标对象
    private Object target;

    //使用构造方法传递目标对象
    public CglibAgent(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 class CglibDemo {
    public static void main(String[] args) {
        Singer singer = new Singer();
        CglibAgent cglibAgent = new CglibAgent(singer);
        Sing sing = (Sing)cglibAgent.createProxy();
        sing.singSongs();

        System.out.println("--------separator--------");

        Dancer dancer = new Dancer();
        CglibAgent dancerAgent = new CglibAgent(dancer);
        Dancer proxy = (Dancer) dancerAgent.createProxy();
        proxy.dance();
    }
}

result

这是增强方法前......
singer can sing songs
这是增强方法后......
--------separator--------
这是增强方法前......
dancer can dance
这是增强方法后......

总结

方式 优点 缺点
静态代理 简单,需实现统一接口 扩展性差,性能
JDK动态代理 耦合低,需实现统一接口 性能
CGLIB动态代理 不需实现统一接口,代理类不能是final 性能

代码 proxy-demo

参考
静态代理、JDK动态代理和CGLIB动态代理之间的区别?
代理模式

相关文章

  • Java代理模式及三种方式

    导读 移动开发知识体系总章(Java基础、Android、Flutter) 代理模式简介 Java的三种代理模式 ...

  • java动态代理(JDK和cglib)(转载自http://ww

    java动态代理(JDK和cglib) JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他的特征是...

  • Java基础:反射

    反射注解动态代理相关阅读 Java基础:类加载器 Java基础:反射 Java基础:注解 Java基础:动态代理 ...

  • java基础-代理模式

    1.代理模式 为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象...

  • Java基础-代理模式

    代理模式是什么? 首先搞清楚代理是什么,代理就是代替你去做你做的事情。比如你买东西,你不会直接去厂家买,你都是通过...

  • java中的代理模式与装饰者模式的区别

    java中的代理模式与装饰者模式的区别 代理模式与装饰者模式看起来很像,都实现基础对象实现的接口,在其自身对象中都...

  • 《设计模式之禅》读书笔记-2.6-代理模式

    2.6 代理模式 代理的原理可先参看此文章:Java基础-001-枚举、反射、类加载器、内省、注解、泛型、代理 定...

  • Java代理模式之JDK动态代理

    了解什么是动态代理模式,可参考Java设计模式之代理模式 简介 JDK动态代理是java.lang.reflect...

  • java代理模式的那些事

    java代理模式-登场 什么是代理模式? 代理模式是java中的一种设计模式,它其实就是设置一个中间环节来代理你要...

  • java建造者模式

    其他设计模式java单例模式java建造者模式java策略模式java代理模式java观察者模式java适配器模式...

网友评论

      本文标题:java基础-代理模式

      本文链接:https://www.haomeiwen.com/subject/vqoomctx.html