Java JDK动态代理机制

阳光穿透心脏的1/2处 2022-01-14 13:05 372阅读 0赞

最近写了一个简单的ORM数据库框架,需要动态实现接口,用到了动态代理,这里记录一下动态代理的实现。

在Java JDK动态代理机制中,最重要的是一个接口(java.lang.reflect.InvocationHandler)和一个类(java.lang.reflect.Proxy)。

jdk动态代理机制有个鲜明的特点:需要代理的类,必须实现某个接口,如果类中出现接口以外的方法,那么产生的动态代理类中是没有该方法的。也就是说,如果某个类没有实现任何接口,那么这个类就不能同JDK产生动态代理。

如想实现动态代理类,请参考cglib 动态代理机制 https://blog.csdn.net/k_young1997/article/details/93187058

1、java.lang.reflect.InvocationHandler 接口

InvocationHandler 接口的源码:

  1. package java.lang.reflect;
  2. public interface InvocationHandler {
  3. public Object invoke(Object proxy, Method method, Object[] args)
  4. throws Throwable;
  5. }

它定义了一个方法 invoke 其中有三个参数 Object proxyObject[] argsMethod method

  • Object proxy :所需代理的类的真实对象
  • Method method :所需代理的对象中的某个方法的对象
  • Object[] args :该方法接收到的参数

invoke 方法用来执行所代理对象中的方法,其返回值类型是 Object ,是因为返回值是所执行方法的返回值。

2、java.lang.reflect.Proxy类

  1. Proxy类最常用的是 `newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)` 静态方法,用该方法可以获得一个动态代理出的对象。

该方法有三个参数:

  • ClassLoader loader :一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载
  • Class<?>[] interfaces :一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了
  • InvocationHandler h :一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上

通过 Proxy.newProxyInstance 创建的代理对象是在jvm运行时动态生成的一个对象,它并不是我们的InvocationHandler类型,也不是我们定义的那组接口的类型,而是在运行是动态生成的一个对象,并且命名方式都是这样的形式,以$开头,proxy为中,最后一个数字表示对象的标号。

3、代码演示

在newProxyInstance 方法中需要一个 InvocationHandler 对象,所以先创建一个 InvocationHandler 对象。

  1. package demo;
  2. import java.lang.reflect.InvocationHandler;
  3. import java.lang.reflect.Method;
  4. public class MethodProxy implements InvocationHandler {
  5. private Object obj;
  6. public MethodProxy(Object obj) {
  7. this.obj = obj;
  8. }
  9. //如果你动态代理的是没有实现接口的,以上代码可以省略,下边invoke方法不用执行,
  10. //改为自己想要执行的代码
  11. @Override
  12. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  13. //方法前后都可以加入自己想执行的代码
  14. return method.invoke(obj, args);
  15. }
  16. }

需代理类接口

  1. package demo;
  2. public interface User {
  3. public void hello();
  4. }

需代理类

  1. package demo;
  2. public class UserImpl implements User {
  3. @Override
  4. public void hello() {
  5. System.out.println("Hello Word");
  6. }
  7. }

该类调用 Proxy.newProxyInstance 方法获得一个动态代理的对象

  1. package demo;
  2. import java.lang.reflect.Proxy;
  3. public class ProxyTest {
  4. public static void main(String[] args) {
  5. User user = (User) Proxy.newProxyInstance(User.class.getClassLoader(), new Class[] {User.class}, new MethodProxy(new UserImpl()));
  6. user.hello();
  7. }
  8. }

发表评论

表情:
评论列表 (有 0 条评论,372人围观)

还没有评论,来说两句吧...

相关阅读

    相关 代理-jdk动态代理

    1、基于接口的实现,要jdk动态代理的类必须要实现一个接口; 2、中介类:实现了InvocationHandler,并重写这个接口的 方法(public Object inv

    相关 深入理解JDK动态代理机制

    一、现实生活中的代理?         在现实生活中,我们常见的有服务器代理商、联想PC代理商、百事可乐、火车票、机票等代理商,为什么会有这些个代理商呢?设想以买火车票为