• 设计模式—结构型模式之代理模式


    设计模式—结构型模式之代理模式

    代理模式(Proxy Pattern) ,给某一个对象提供一个代理,并由代理对象控制对原对象的引用,对象结构型模式。

    静态代理

    比如我们有一个直播平台,提供了直播功能,但是如果不进行美颜,可能就比较冷清。所以美颜功能就是我们的增强,可以用静态代理来实现。

    直播接口:

    /**
     * 直播接口
     */
    public interface LiveBroadCastInterface {
        void liveBroadcast();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    直播类:

    /**
     * 实现直播接口
     */
    public class SjdwzLiveBroadCast implements LiveBroadCastInterface{
        @Override
        public void liveBroadcast() {
            System.out.println("我来直播了......");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    如果没有美颜,可能就会比较冷清;所以我们可以提供一个静态代理,来为我们的直播进行增强。

    要代理的功能类要和原类型实现相同的接口。

    public class SjdwzStaticProxy implements  LiveBroadCastInterface{
        
        private LiveBroadCastInterface liveBroadCastInterface;
    
        public SjdwzStaticProxy(LiveBroadCastInterface liveBroadCastInterface) {
            this.liveBroadCastInterface = liveBroadCastInterface;
        }
    
        @Override
        public void liveBroadcast() {
            System.out.println("这是代理的功能");
            System.out.println("美颜--------");
            System.out.println("=========原功能如下=========");
            this.liveBroadCastInterface.liveBroadcast();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    测试类如下:

    public class StaticSjdwzProxyTest {
        public static void main(String[] args) {
            SjdwzStaticProxy sjdwzStaticProxy = new SjdwzStaticProxy(new SjdwzLiveBroadCast());
            sjdwzStaticProxy.liveBroadcast();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    运行如下:

    运行截图

    jdk动态代理

    还是上面的例子,可以使用JDK的动态代理来实现:

    /**
     * 实现InvocationHandler的作用是为了在本类实现增强方法,
     * @param  要代理对象实现的接口
     */
    public class JdkLiveBroadCastProxy<T> implements InvocationHandler {
    
        //被代理对象
        private T target;
    
        public JdkLiveBroadCastProxy(T target) {
            this.target = target;
        }
    
        public static<T> T getProxy(T t){
            /**
             * ClassLoader loader, 当前被代理对象的类加载器
             * Class[] interfaces, 当前被代理对象所实现的所有接口
             * InvocationHandler h,
             *  当前被代理对象执行目标方法的时候我们使用h可以定义拦截增强方法
             */
            Object o = Proxy.newProxyInstance(
                    t.getClass().getClassLoader(),
                    t.getClass().getInterfaces(), //必须接口
                    new JdkLiveBroadCastProxy(t));
            return (T)o;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("这是代理的一些功能======");
            System.out.println("原本的功能===========");
            //反射执行
            Object invoke = method.invoke(this.target, args);
            System.out.println("返回值:"+invoke);
            return invoke;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    测试类如下:

    public class JdkLiveBroadCastProxyTest {
        public static void main(String[] args) {
            LiveBroadCastInterface proxy = JdkLiveBroadCastProxy.getProxy(new SjdwzLiveBroadCast());
            proxy.liveBroadcast();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    运行结果如下:

    运行截图

    要求

    JDK要求被代理对象必须有接口,因为必须有接口才能告诉代理有哪些方法。

    cglib动态代理

    我们发现,如果使用JDK的动态代理,必须实现接口。cglib动态代理是不需要实现接口的。

    首先我们在项目的pom文件中引入依赖:

    <dependency>
        <groupId>cglibgroupId>
        <artifactId>cglibartifactId>
        <version>3.3.0version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    cglib动态代理类如下:

    public class CglibProxy {
    
        //为任意对象创建代理
        public static<T> T createProxy(T t){
            //1、创建一个增强器
            Enhancer enhancer = new Enhancer();
    
            //2、设置要增强哪个个类的功能。增强器为这个类动态创建一个子类
            enhancer.setSuperclass(t.getClass());
    
            //3、设置回调
            enhancer.setCallback(new MethodInterceptor() {
                @Override
                public Object intercept(Object obj,
                                        Method method,  //为了能获取到原方法的一些元数据信息
                                        Object[] args,
                                        MethodProxy proxy) throws Throwable {
                    //编写增强的逻辑
                    System.out.println("cglib的动态代理增强的功能===========");
                    System.out.println("原功能===========");
                    //目标方法进行执行
                    Object invoke = proxy.invokeSuper(obj,args);
                    return invoke;
                }
            });
    
            Object o = enhancer.create();
            return (T) o;
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    测试类如下:

    public class MyCglibProxyTest {
        public static void main(String[] args) {
            SjdwzLiveBroadCast proxy = CglibProxy.createProxy(new SjdwzLiveBroadCast());
            proxy.liveBroadcast();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    运行截图如下:

    运行结果

  • 相关阅读:
    学生类定义(类和对象)Java
    MBps与Mbps区别
    干货 | 科研人的KPI怎么算,H指数和G指数是什么
    windows10下安装fbprophet及使用虚拟环境
    深度学习参数初始化(一)Xavier初始化 含代码
    Visual Studio 线性表的链式存储节点输出引发异常:读取访问权限冲突
    复杂环境下人形机器人自动导航项目复盘
    暗物质探测器认知教学VR元宇宙平台打破传统束缚
    JavaScript 输出
    操作系统之虚拟内存总结
  • 原文地址:https://blog.csdn.net/qq_41243472/article/details/134388259