Java的动态代理和静态代理及反射常用API详解

 更新时间:2024年01月15日 08:35:43   作者:小汤汤汤汤  
这篇文章主要介绍了Java的动态代理和静态代理及反射常用API详解,动态代理是一种在运行时动态生成代理对象的技术,它是一种设计模式,用于在不修改原始对象的情况下,通过代理对象来间接访问原始对象,并在访问前后执行额外的操作,需要的朋友可以参考下

JDK动态代理

我们看下JDK动态代理的实现步骤:

第一步:创建接口,JDK动态代理基于接口实现,所以接口必不可少(准备工作)

第二步:实现InvocationHandler接口,重写invoke方法(准备工作)

第三步:调用Proxy的静态方法newProxyInstance方法生成代理实例(生成实例时需要提供类加载器,我们可以使用接口类的加载器即可)

第四步:使用新生成的代理实例调用某个方法实现功能。

我们的动态代理实现过程中根本没有涉及到真实类实例。

静态代理

 package ceshi1;
 public interface Iuser {
     void eat(String s);
 }
package ceshi1;
public class UserImpl implements Iuser {
  @Override
  public void eat(String s) {
    System.out.println("我要吃"+s);
  }
}
package ceshi1;
public class UserProxy implements Iuser {
  private Iuser user = new UserImpl();
  @Override
  public void eat(String s) {
    System.out.println("静态代理前置内容");
    user.eat(s);
    System.out.println("静态代理后置内容");
  }
}
package ceshi1;
public class ProxyTest {
  public static void main(String[] args) {
    UserProxy proxy = new UserProxy();
    proxy.eat("苹果");
  }
}

动态代理

package ceshi1;
 public interface Iuser {
   void eat(String s);
 }
package ceshi1;
public class UserImpl implements Iuser {
  @Override
  public void eat(String s) {
    System.out.println("我要吃"+s);
  }
}
package ceshi1;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class DynamicProxy implements InvocationHandler {
  private Object object;//用于接收具体实现类的实例对象
  //使用带参数的构造器来传递具体实现类的对象
  public DynamicProxy(Object obj){
    this.object = obj;
  }
  @Override
  public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
    System.out.println("前置内容");
    method.invoke(object, args);
    System.out.println("后置内容");
    return null;
  }
}
package ceshi1;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class ProxyTest {
  public static void main(String[] args) {
    Iuser user = new UserImpl();
    InvocationHandler h = new DynamicProxy(user);
    Iuser proxy = (Iuser) Proxy.newProxyInstance(Iuser.class.getClassLoader(), new Class[]{Iuser.class}, h);
    proxy.eat("苹果");
  }
}

反射

JDK 提供的反射 API 进行反射调用:

Class clz = Class.forName("com.chenshuyi.reflect.Apple");
Method method = clz.getMethod("setPrice", int.class);
Constructor constructor = clz.getConstructor();
Object object = constructor.newInstance();
method.invoke(object, 4);

一般情况下我们使用反射获取一个对象的步骤:

获取类的 Class 对象实例

Class clz = Class.forName("com.zhenai.api.Apple");

根据 Class 对象实例获取 Constructor 对象

Constructor appleConstructor = clz.getConstructor();

使用 Constructor 对象的 newInstance 方法获取反射类对象

Object appleObj = appleConstructor.newInstance();

而如果要调用某一个方法,则需要经过下面的步骤:

获取方法的 Method 对象

Method setPriceMethod = clz.getMethod("setPrice", int.class);

利用 invoke 方法调用方法

setPriceMethod.invoke(appleObj, 14);

反射常用API

在 Java API 中,获取 Class 类对象有三种方法:

第一种,使用 Class.forName 静态方法。当你知道该类的全路径名时,你可以使用该方法获取 Class 类对象。

Class clz = Class.forName("java.lang.String");

第二种,使用 .class 方法。

这种方法只适合在编译前就知道操作的 Class。

Class clz = String.class;

第三种,使用类对象的 getClass() 方法。

String str = new String("Hello");

Class clz = str.getClass();

通过反射创建类对象

通过反射创建类对象主要有两种方式:通过 Class 对象的 newInstance() 方法、通过 Constructor 对象的 newInstance() 方法。

第一种:通过 Class 对象的 newInstance() 方法。

Class clz = Apple.class;
Apple apple = (Apple)clz.newInstance();

第二种:通过 Constructor 对象的 newInstance() 方法

Class clz = Apple.class;
Constructor constructor = clz.getConstructor();
Apple apple = (Apple)constructor.newInstance();

通过 Constructor 对象创建类对象可以选择特定构造方法,而通过 Class 对象则只能使用默认的无参数构造方法。下面的代码就调用了一个有参数的构造方法进行了类对象的初始化。

Class clz = Apple.class;
Constructor constructor = clz.getConstructor(String.class, int.class);
Apple apple = (Apple)constructor.newInstance("红富士", 15);

我们通过 Class 对象的 getFields() 方法可以获取 Class 类的属性,但无法获取私有属性。

Class clz = Apple.class;
Field[] fields = clz.getFields();
for (Field field : fields) {
    System.out.println(field.getName());
}

而如果使用 Class 对象的 getDeclaredFields() 方法则可以获取包括私有属性在内的所有属性:

Class clz = Apple.class;
Field[] fields = clz.getDeclaredFields();
for (Field field : fields) {
    System.out.println(field.getName());
}

到此这篇关于Java的动态代理和静态代理及反射常用API详解的文章就介绍到这了,更多相关Java动态代理和反射内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Maven中央仓库地址配置大全

    Maven中央仓库地址配置大全

    这篇文章主要介绍了Maven中央仓库地址配置大全,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-06-06
  • MyBatis全局映射文件实现原理解析

    MyBatis全局映射文件实现原理解析

    这篇文章主要介绍了MyBatis全局映射文件实现原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-08-08
  • 解决idea中svn提交时performing vcs refresh时间很长的问题

    解决idea中svn提交时performing vcs refresh时间很长的问题

    这篇文章主要介绍了解决idea中svn提交时performing vcs refresh时间很长的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-09-09
  • Java中string和int的互相转换问题

    Java中string和int的互相转换问题

    本文通过实例代码给大家详细介绍了Java中string和int的互相转换问题,感兴趣的朋友一起看看吧
    2017-10-10
  • Java设计模式之Template Pattern模板模式详解

    Java设计模式之Template Pattern模板模式详解

    这篇文章主要介绍了Java设计模式之Template Pattern模板模式详解,模板模式(Template Pattern)行为型模式之一,抽象父类定义一个操作中的算法的骨架,而将一些步骤延迟到子类中,需要的朋友可以参考下
    2023-10-10
  • Java零基础教程之do-while循环语句实例

    Java零基础教程之do-while循环语句实例

    Java中的do-while循环是一种后测试循环语句,它类似于while循环,但它先执行循环体中的代码,然后再进行条件判断,无论条件是否满足,至少会执行一次循环体中的代码,这篇文章主要给大家介绍了关于Java零基础教程之do-while循环语句的相关资料,需要的朋友可以参考下
    2024-09-09
  • SpringBoot引入swagger报错处理的解决方法

    SpringBoot引入swagger报错处理的解决方法

    这篇文章主要给大家介绍SpringBoot引入swagger是会出现报错的处理解决方法,文中有详细的解决过程,感兴趣的小伙伴可以跟着小编一起来学习吧
    2023-06-06
  • Java中四种引用详解

    Java中四种引用详解

    这篇文章主要为大家介绍了Java中的四种引用,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2021-12-12
  • IntelliJ IDEA 如何配置git的操作方法

    IntelliJ IDEA 如何配置git的操作方法

    这篇文章主要介绍了IntelliJ IDEA 如何配置git,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-08-08
  • Java音频处理之音频流转音频文件和获取音频播放时长详解

    Java音频处理之音频流转音频文件和获取音频播放时长详解

    这篇文章主要为大家详细介绍了如何使用Java实现音频流转音频文件和获取音频播放时长功能,文中的示例代码简洁易懂,有需要的小伙伴可以了解下
    2025-07-07

最新评论