Java设计模式之代理模式

Java设计模式之代理模式,第1张

Java设计模式代理模式

文章目录
  • Java设计模式之代理模式
  • 前言
  • 一、代理模式
  • 二、使用场景
  • 三、静态代理
    • 1. 抽象主题类
    • 2. 真实主题类
    • 3. 代理类
    • 4. 客户端
  • 四、JDK动态代理
    • 1. 抽象主题类
    • 2. 真实主题类
    • 3. JDK代理工厂
    • 4. 客户端
  • 五、CGLib代理
    • 1. 真实主题类
    • 2. CGLib代理工厂
    • 3. 客户端
  • 总结
    • 1. 优点
    • 2. 缺点
    • 3. Spring中代理选择原则


前言
  • 掌握代理模式的应用场景和实现原理
  • 了解静态代理和动态代理的区别
  • 了解CGLib和JDK Proxy的根本区别
  • 手写实现动态代理

一、代理模式

代理模式(Proxy Pattern)是指为其他对象提供一种代理,以控制对这个对象的访问
代理对象在客户端和目标对象之间起到中介作用
根据代理的创建时期,代理模式分为静态代理和动态代理

二、使用场景
  • 保护目标对象
  • 增强目标对象
三、静态代理

由程序员创建代理类或特定工具自动生成源代码再对其编译,在程序运行前代理类的 .class 文件就已经存在了。显示声明被代理的对象

1. 抽象主题类
/**
 * 抽象主题
 */
public interface ISubject {
    void request();
}
2. 真实主题类
/**
 * 真实主题
 */
public class RealSubject implements ISubject {
    @Override
    public void request() {
        System.out.println("真实主题方法");
    }
}
3. 代理类
/**
 * 代理类
 */
public class Proxy implements ISubject {
    private RealSubject realSubject;

    public Proxy(RealSubject realSubject) {
        this.realSubject = realSubject;
    }

    @Override
    public void request() {
        System.out.println("访问前。。。");
        realSubject.request();
        System.out.println("访问后。。。");
    }
}
4. 客户端
public class Client {
    public static void main(String[] args) {
        Proxy proxy = new Proxy(new RealSubject());
        proxy.request();
    }
}
四、JDK动态代理

生成逻辑较为简单,效率较低,底层通过反射方式实现,必须要求代理的目标对象一定要实现一个接口

1. 抽象主题类
/**
 * 抽象主题
 */
public interface ISubject {
    void request();
}
2. 真实主题类
/**
 * 真实主题
 */
public class RealSubject implements ISubject {
    @Override
    public void request() {
        System.out.println("真实主题方法");
    }
}
3. JDK代理工厂
/**
 * 代理工厂
 */
public class ProxyFactory implements InvocationHandler {
    private Object target;

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

    public Proxy getTarget() {
        return (Proxy) Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }

    @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;
    }
}
4. 客户端
public class Client {
    public static void main(String[] args) {
        ProxyFactory proxy = new ProxyFactory(new RealSubject());
        ISubject target = (ISubject) proxy.getTarget();
        target.request();
    }
}
五、CGLib代理

CGLib效率更高,性能也更高,底层没有用到反射(final修饰的方法无法被代理),采用继承的方式,覆盖父类的方法

1. 真实主题类
/**
 * 真实主题
 */
public class RealSubject {
    public void request() {
        System.out.println("真实主题方法");
    }
}
2. CGLib代理工厂
/**
 * 代理工厂
 */
public class CGLibFactory implements MethodInterceptor {
    public Object getTarget(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 {
        System.out.println("访问前");
        Object invoke = methodProxy.invokeSuper(o, objects);
        System.out.println("访问后");
        return invoke;
    }
}
3. 客户端
public class Client {
    public static void main(String[] args) {
        RealSubject target = (RealSubject) new CGLibFactory().getTarget(RealSubject.class);
        target.request();
    }
}

总结 1. 优点
  • 代理模式能将代理对象与真实被调用的目标对象分离
  • 一定程度上降低了系统的耦合程度,易于扩展
  • 代理可以起到保护目标对象的作用
  • 增强目标对象的职责
2. 缺点
  • 代理模式会造成系统设计中类的数目增加
  • 在客户端和目标对象之间增加了一个代理对象,请求处理速度变慢
  • 增加了系统的复杂度
3. Spring中代理选择原则
  • 当Bean有实现接口时,Spring会JDK动态代理
  • 当Bean没有实现接口时,Spring会选择CGLib代理
  • Spring可以通过配置强制使用CGLib代理

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/797115.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-06
下一篇 2022-05-06

发表评论

登录后才能评论

评论列表(0条)

保存