美文网首页
静态代理与动态代理

静态代理与动态代理

作者: Sheldonlv | 来源:发表于2019-12-08 03:29 被阅读0次

    简介

    看了挺多关于代理方面的文章,这是我个人对代理的一些粗浅的理解。

    代理模式是一种毕竟常见的设计模式。
    就好比歌手要开展演唱会,背后会有一个经纪人帮忙接活动,时间安排等。
    在这里,歌手就是提供服务的对象,而经纪人就是代理。
    而代理又分为 静态代理动态代理

    静态代理

    组成结构:

    1. 接口类
    2. 接口对象
    3. 代理类
    /**
     * 1.歌手接口
     */
    public interface Singer {
        // 歌手有唱歌这么个天赋
        public void singsong();
    }
    
    /**
     * 2.歌手的实例化-对象(刘德华)
     */
    public class LiuSinger implements Singer{
    
        @Override
        public void singsong(){
            System.out.println("刘德华-正在激情演唱歌曲XXX");
        }
    }
    
    package test2;
    
    /**
     * 3.静态代理类
     * Created by Sheldon on 2019/11/5.
     */
    public class SingerStaticProxy implements Singer{
    
        // 歌手这一成员变量
        private Singer singer;
    
        public SingerStaticProxy(Singer singer){
            this.singer = singer;
        }
    
        // 唱歌之前
        public void beforeSing(){
            System.out.println("布置会场ing");
        }
    
        // 唱歌之后
        public void afterSing(){
            System.out.println("清理会场ing");
        }
    
        @Override
        public void singsong(){
            // 调用之前的操作
            beforeSing();
            // 调用代理对象的操作
            singer.singsong();
            // 调用之后的操作
            afterSing();
        }
    
        // 测试方法
        public static void main(String[] args) {
            // 创建歌手对象
            Singer singer = new LiuSinger();
            // 创建代理对象
            SingerStaticProxy proxy = new SingerStaticProxy(singer);
            // 调用歌手操作
            proxy.singsong();
        }
    }
    
    静态代理测试

    动态代理

    区别

    1. 静态代理 通常只代理一个类,动态代理是代理一个接口下的多个实现类。
    2. 静态代理 事先知道要代理的是什么,而动态代理不知道要代理什么东西,只有在运行时才知道。
    3. 静态代理 由程序员创建代理类或特定工具自动生成源代码再对其编译。
    4. 动态代理 是实现 JDK 里的 InvocationHandler 接口的 invoke 方法,但注意的是代理的是接口,也就是你的业务类必须要实现接口,通过 Proxy 里的 newProxyInstance 得到代理对象。

    AOP 便是通过动态代理实现的
    一般通过以下固定的套路实现的。

    方法一:

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    /**
     * 动态代理
     * Created by Sheldon on 2019/11/5.
     */
    public class SingerDynamicProxy implements InvocationHandler {
    
        // 代理的对象
        private Object object;
    
        public SingerDynamicProxy(Object object){
            this.object = object;
        }
    
        // 唱歌之前
        public void beforeSing(){
            System.out.println("动态-布置会场ing");
        }
    
        // 唱歌之后
        public void afterSing(){
            System.out.println("动态-清理会场ing");
        }
    
        /**
         * 代理对象要执行的方法:{即真正需要执行的代理对象的业务方法}
         * @param o   参数1:代理类对象
         * @param method  参数2:被代理对象的业务方法 {注意:这里是概论的即统一所有的被代理对象的方法都用method表示,具体的是什么方法就需要具体的传入被代理对象来决定}
         * @param arg    参数3:被代理对象的方法的参数
         * @return
         */
        @Override
        public Object invoke(Object o, Method method, Object[] arg) throws Throwable {
            // 切面代码
            beforeSing();
            // 要执行的被代理对象的业务方法
            Object obj = method.invoke(object, arg);
            // 切面代码
            afterSing();
            return null;
        }
    
        // 测试类
        public static void main(String[] args) {
            // 创建刘德华歌手
            LiuSinger liu = new LiuSinger();
            // 创建代理对象
            SingerDynamicProxy proxy = new SingerDynamicProxy(liu);
            // 绑定歌手跟代理的关系
            // getClassLoader()叫类加载器:把一个类加载到内存里面
            // getInterfaces() 获取类的所有接口方法
            // proxy 传入要绑定的代理对象
            Singer singer = (Singer) Proxy.newProxyInstance(
                    liu.getClass().getClassLoader(),
                    liu.getClass().getInterfaces(),
                    proxy);
            // 调用歌手方法
            singer.singsong();
        }
    }
    

    方法二:

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    /**
     * 动态代理
     * Created by Sheldon on 2019/11/5.
     */
    public class SingerDynamicProxy implements InvocationHandler {
    
        // 代理的对象
        private Object object;
    
        public SingerDynamicProxy(Object object){
            this.object = object;
        }
    
        // 唱歌之前
        public void beforeSing(){
            System.out.println("动态-布置会场ing");
        }
    
        // 唱歌之后
        public void afterSing(){
            System.out.println("动态-清理会场ing");
        }
    
        // 绑定关系(返回绑定好关系的代理实例)
        // getClassLoader()叫类加载器:把一个类加载到内存里面
        // getInterfaces() 获取类的所有接口方法
        // 如下是固定的写法,套路来的,得到代理对象(与传入对象有关)
        public Object newProxyInstance(){
            return Proxy.newProxyInstance(
                    object.getClass().getClassLoader(),
                    object.getClass().getInterfaces(),
                    this);
        }
    
        /**
         * 代理对象要执行的方法:{即真正需要执行的代理对象的业务方法}
         * @param o   参数1:代理类对象
         * @param method  参数2:被代理对象的业务方法 {注意:这里是概论的即统一所有的被代理对象的方法都用method表示,具体的是什么方法就需要具体的传入被代理对象来决定}
         * @param arg    参数3:被代理对象的方法的参数
         * @return
         */
        @Override
        public Object invoke(Object o, Method method, Object[] arg) throws Throwable {
            // 切面代码
            beforeSing();
            // 要执行的被代理对象的业务方法
            Object obj = method.invoke(object, arg);
            // 切面代码
            afterSing();
            return null;
        }
    
        // 测试类
        public static void main(String[] args) {
            // 创建刘德华歌手
            LiuSinger liu = new LiuSinger();
            // 创建代理对象
            SingerDynamicProxy proxy = new SingerDynamicProxy(liu);
            // 获取代理对象实例
            Singer proxyInstance = (Singer) proxy.newProxyInstance();
            // 调用歌手方法
            proxyInstance.singsong();
        }
    }
    
    动态代理demo测试

    相关文章

      网友评论

          本文标题:静态代理与动态代理

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