设计模式-代理模式(delegate)

什么是代理?

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

这里使用到编程中的一个思想:不要随意去修改别人已经写好的代码或者方法,如果需改修改,可以通过代理的方式来扩展该方法

举个例子来说明代理的作用:假设我们想邀请一位明星,那么并不是直接连接明星,而是联系明星的经纪人,来达到同样的目的.明星就是一个目标对象,他只要负责活动中的节目,而其他琐碎的事情就交给他的代理人(经纪人)来解决.这就是代理思想在现实中的一个例子

java中的代理类型

静态代理

  • 代理对象和目标对象(委托对象)都要实现相同的接口;

  • 当有很多目标需要被代理时,需要手动写很多代理类,会造成代码重复和膨胀;

动态代理

  • 目标对象需要实现接口,代理对象不需要实现接口;

  • 能在运行时自动生成代理对象,不需要手动写很多代理类,不会有代码重复和膨胀;

demo
java 复制代码
package delegate.jdk;

public interface IHello {
    String hello(String name);
}
java 复制代码
package delegate.jdk;

public class HelloImpl implements IHello {
    @Override
    public String hello(String name) {
        return "Hello, " + name;
    }
}
java 复制代码
package delegate.jdk;

import java.lang.reflect.Proxy;

public class RuntimeProxyFactory {
    public static Object createProxy(Object target) {
        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                (proxy, method, args) -> {
                    long startTimeStamp = System.currentTimeMillis();
                    Object returnValue = method.invoke(target, args);
                    long endTimeStamp = System.currentTimeMillis();
                    long runtime = endTimeStamp - startTimeStamp;
                    System.out.println("Runtime: " + runtime);
                    return returnValue;
                }
        );
    }
}
java 复制代码
package delegate.jdk;

public class ProxyTest {
    public static void main(String[] args) {
        IHello hello = (IHello) RuntimeProxyFactory.createProxy(new HelloImpl());
        System.out.println(hello.hello("Lee"));
    }
}
原理分析(todo)

cglib代理

  • 目标类也不需要实现接口;(代理类继承目标类,以目标类子类的方式实现代理,所以也叫子类代理,因为是基于继承实现,所以目标类及其方法不能被final修饰)

demo

java 复制代码
package delegate.cglib;

public class Hello {

    public String hello(String name) {
        return "Hello, " + name;
    }

}
java 复制代码
package delegate.cglib;

import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class RuntimeInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        long startTimeStamp = System.currentTimeMillis();
        Object returnValue = methodProxy.invokeSuper(o, objects);
        long endTimeStamp = System.currentTimeMillis();
        long runtime = endTimeStamp - startTimeStamp;
        System.out.println("Runtime: " + runtime);
        return returnValue;
    }
}
java 复制代码
package delegate.cglib;

import org.springframework.cglib.proxy.Enhancer;

public class RuntimeProxyFactory {
    public static Object createProxy(Object target) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(new RuntimeInterceptor());
        return enhancer.create();
    }
}
java 复制代码
package delegate.cglib;

public class ProxyTest {
    public static void main(String[] args) {
        Hello hello = (Hello) RuntimeProxyFactory.createProxy(new Hello());
        System.out.println(hello.hello("Lee"));
    }
}

原理分析(todo)

Spring AOP中的动态代理

在Spring的AOP编程中:如果加入容器的目标对象有实现接口,用JDK代理;如果目标对象没有实现接口,用Cglib代理。

参考资料

  1. Java的三种代理模式

  2. Spring | Aop核心 | Cglib源码详细解析

  3. https://km.sankuai.com/collabpage/1584727104

相关推荐
fengfuyao9853 小时前
MATLAB实现自适应动态规划(ADP)方法
matlab·动态规划·代理模式
geovindu3 天前
go: Proxy Pattern
开发语言·后端·设计模式·golang·代理模式
我爱cope6 天前
【从0开始学设计模式-12| 代理模式】
设计模式·代理模式
两年半的个人练习生^_^7 天前
每日一学:设计模式之代理模式
java·设计模式·代理模式
天若有情6738 天前
用动态规划思路,一步一步实现响应式数据(从本质到落地)
算法·动态规划·代理模式
希望永不加班9 天前
Spring AOP 代理模式:CGLIB 与 JDK 动态代理区别
java·开发语言·后端·spring·代理模式
阿Y加油吧10 天前
动态规划经典题解:最长递增子序列 & 乘积最大子数组
算法·动态规划·代理模式
计算机安禾11 天前
【数据结构与算法】第48篇:算法思想(三):贪心算法
c语言·开发语言·数据结构·算法·贪心算法·代理模式·图论
Java成神之路-12 天前
零基础入门:动态代理与 Spring AOP 核心知识点总结
spring·代理模式
阿Y加油吧12 天前
从斐波那契到动态规划:两道入门题吃透 DP 核心思想
算法·动态规划·代理模式