美文网首页
java 基本知识之代理

java 基本知识之代理

作者: 瀚海网虫 | 来源:发表于2019-12-27 13:43 被阅读0次

    1. 静态代理

    简言之
    代理对象 = 增强代码+ 目标对象(原对象)

    /**
     * 快递员
     */
    public class Courier implements IBuy{
        @Override
        public void buy() {
            System.out.println("买一瓶药");
        }
    }
    
    public interface IBuy {
        void buy();
    }
    
    public class SFCourierProxy {
        // 接收目标对象,以便调用buy方法
        private IBuy courier;
        public SFCourierProxy(IBuy courier) {
            this.courier = courier;
        }
        // 对目标对象的buy方法进行功能扩展
        public void buy() {
            System.out.println("所有的药都来自大药店");
            courier.buy();
            System.out.println("药买好后,将会第一时间送到您身边");
        }
    }
    
    public class TestProxy {
        public static void main(String[] args) {=
            IBuy courier = new Courier();
            SFCourierProxy sfCourierProxy = new SFCourierProxy(courier);
            sfCourierProxy.buy();
        }
    }
    

    输出结果

    所有的药都来自大药店
    买一瓶药
    药买好后,将会第一时间送到您身边
    

    1.1 优点

    1. 不直接操作原对象,隔离性好
    2. 增加原对象功能,修饰或者新增功能方便

    1.2 缺点

    1. 代理对象通常与原对象是1对1关系(当然也可以是1对多),如果需要被代理
    2. 的对象多,会导致代理类激增,带来冗余与增加维护成本。
    3. 被代理类发生改变时,代理类也需要改变

    2. 动态代理

    类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在Jvm的方法区内,然后在区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构。类的加载的最终产品是位于堆区中的Class对象,Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接口。

    image.png

    类对象的创建过程


    image.png image.png

    Java 中的所有类型包括基本类型(int, long, float等等),即使是数组都有与之关联的 Class 类的对象。

    Class对象是由Jvm自动生成的,每当一个类被载入时,Jvm就自动为其生成一个Class对象

    作者:dsying
    链接:https://juejin.im/post/5dac4edff265da5b5f7588d1
    来源:掘金
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    两个核心类:Proxy 与 InvocationHandler

    public interface UserService {
        public void select();
        public void update();
    }
    
    public class UserServiceImpl implements UserService {
        @Override
        public void select() {
            System.out.println("查询 selectById");
        }
        @Override
        public void update() {
            System.out.println("更新 update");
        }
    }
    
    public class LogDynamicProxy implements InvocationHandler {
        Object target;  // 被代理的对象,实际的方法执行者
    
        public LogDynamicProxy(Object target) {
            this.target = target;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            before();
            Object object = method.invoke(target, args);
            end();
            return object;
        }
    
        private void before() {
            System.out.println(String.format("log start time [%s]",new Date()));
        }
    
        private void end() {
            System.out.println(String.format("log end time [%s]",new Date()));
        }
    }
    
    public class LogDynamicProxy2 implements InvocationHandler {
        ....
        public <T> T getProxy() {
            return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
        }
    }
    
    public class DynamicProxyTest {
        public static void main(String[] args) {
            UserService userService = new UserServiceImpl();
            LogDynamicProxy logHandler = new LogDynamicProxy(userService);
    
            UserService userService1 = (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(),
                    userService.getClass().getInterfaces(),logHandler);
    
            userService1.select();
            userService1.update();
    
            LogDynamicProxy2 logHandler2 = new LogDynamicProxy2(userService);
            UserService userService2 = logHandler2.getProxy();
            userService2.select();
            userService2.update();
        }
    }
    
    public class DynamicProxyTest {
        public static void main(String[] args) {
            UserService userService = new UserServiceImpl();
            LogDynamicProxy logHandler = new LogDynamicProxy(userService);
    
            UserService userService1 = (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(),
                    userService.getClass().getInterfaces(),logHandler);
            System.out.println("--代理1形式---");
            userService1.select();
            userService1.update();
            
            System.out.println("--代理2形式---");
            LogDynamicProxy2 logHandler2 = new LogDynamicProxy2(userService);
            UserService userService2 = logHandler2.getProxy();
            userService2.select();
            userService2.update();
        }
    }
    
    --代理1形式---
    log start time [Fri Dec 27 11:23:47 CST 2019]
    查询 selectById
    log end time [Fri Dec 27 11:23:47 CST 2019]
    log start time [Fri Dec 27 11:23:47 CST 2019]
    更新 update
    log end time [Fri Dec 27 11:23:47 CST 2019]
    --代理2形式---
    log start time [Fri Dec 27 11:23:47 CST 2019]
    查询 selectById
    log end time [Fri Dec 27 11:23:47 CST 2019]
    log start time [Fri Dec 27 11:23:47 CST 2019]
    更新 update
    log end time [Fri Dec 27 11:23:47 CST 2019]
    

    除了 Proxy.newProxyInstance(userService.getClass().getClassLoader(),
    userService.getClass().getInterfaces(),logHandler);
    还有另一种创建方法 constructor.newInstance(new InvocationHandler()

    public class ProxyTest2 {
        public static void main(String[] args) throws Exception{
           UserService userService = new UserServiceImpl();
           UserService userService1 = (UserService) getProxy(userService);
            userService1.select();
            userService1.update();
        }
        private static Object getProxy(Object object) throws Exception  {
            Class calculatorProxyClazz = Proxy.getProxyClass(UserService.class.getClassLoader(), UserService.class);
            Constructor constructor = calculatorProxyClazz.getConstructor(InvocationHandler.class);
            UserService proxy = (UserService) constructor.newInstance(new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    System.out.println("开始执行方法");
                    UserService userService1 = new UserServiceImpl();
                    Object result = method.invoke(userService1, args);
                    System.out.println("方法名" + method) ;
                    System.out.println("执行方法结束");
                    return result;
                }
            });
            return proxy;
        }
    }
    

    2.1 优点

    1. 动态生成代理对象,解决代理类泛滥问题
    2. 被代理类发生改变时,被代理类不需要改变

    2.2 缺点

    无论静态代理还是动态代理,都需要一个接口。
    如果要包装的防范,没有实现接口怎么办呢?

    3.CGLib 动态代理

    CGLib 是一个类库,它可以在运行期间动态的生成字节码,动态生成代理类。

    相关文章

      网友评论

          本文标题:java 基本知识之代理

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