美文网首页
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 基本知识之代理

    1. 静态代理 简言之代理对象 = 增强代码+ 目标对象(原对象) 输出结果 1.1 优点 不直接操作原对象,隔离...

  • Java 动态代理

    java的动态代理机制详解 JDK动态代理详解 Java核心技术点之动态代理

  • Java代理模式之JDK动态代理

    了解什么是动态代理模式,可参考Java设计模式之代理模式 简介 JDK动态代理是java.lang.reflect...

  • Spring AOP源码解析

    欲了解AOP,需先了解Java动态代理;欲了解Java动态代理,先熟悉设计模式之代理模式。入门有道,先从简学。 1...

  • java之代理技术

    java之代理模式 直接聊技术! 描述 代理模式是常用的java设计模式,代理类主要负责为委托类预处理消息、过滤消...

  • Java设计模式之代理模式

    Java设计模式之代理模式 代理模式 静态代理 动态代理 为什么需要代理 通过代理,我们能够不用知道委托人是谁,而...

  • 找工作(目录)

    知识点 JAVA基本知识 Java基本知识点总结:http://www.jianshu.com/p/6146a2d...

  • 设计模式之代理

    设计模式之代理模式 一、定义 在Java中代理的实现一般分为三种:JDK静态代理、JDK动态代理以及CGLIB动态...

  • java代理之动态代理

    接上一篇:静态代理[https://www.jianshu.com/p/f55f17d8bc75] 有人私信我文章...

  • Java代理之静态代理

    复习一下JAVA的代理,先把常见的静态代理走一遍。注:1.使用代理的目的,始终是为了不改变原有业务代码的情况下,得...

网友评论

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

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