Java反射

Java反射

Posted by Zheng Yang on August 3, 2024

反射在代码和框架中的应用场景

加载数据库驱动

在开发中,我们有时需要根据实际情况动态加载不同的数据库驱动。例如,项目的底层数据库有时使用 MySQL,有时使用 Oracle。这时反射就派上了用场。我们可以通过反射来加载适当的数据库驱动类。

假设我们有以下两个驱动类:

com.mikechen.java.mysqlConnection

com.mikechen.java.oracleConnection

在使用 JDBC 连接数据库时,可以使用 Class.forName() 通过反射加载数据库的驱动程序:


// 加载 MySQL 驱动 

   Class.forName("com.mysql.cj.jdbc.Driver");

  // 加载 Oracle 驱动

   Class.forName("oracle.jdbc.driver.OracleDriver");

配置文件加载

Spring 框架的 IOC(控制反转)就是通过反射机制实现的。Spring 通过配置文件配置各种 Bean,根据需要动态加载和管理这些 Bean,使得程序更加灵活和健壮。

Spring 通过 XML 配置模式装载 Bean 的过程如下:

  1. 将所有 XML 或 properties 配置文件加载入内存。
  2. 解析 XML 或 properties 文件内容,获取实体类的字节码字符串及相关属性信息。
  3. 使用反射机制,根据字符串获取某个类的 Class 实例。
  4. 动态配置实例的属性。

示例

配置文件

application.properties 中定义类名和方法名:

className=com.example.reflectdemo.TestInvoke
methodName=printlnState

实体类

public class TestInvoke {
    private void printlnState() {
        System.out.println("I am fine");
    }
}

解析配置文件内容

// 解析 XML 或 properties 文件内容,得到对应的类名和方法名
public static String getName(String key) throws IOException {
    Properties properties = new Properties();
    FileInputStream in = new FileInputStream("D:\IdeaProjects\AllDemos\language-specification\src\main\resources\application.properties");
    properties.load(in);
    in.close();
    return properties.getProperty(key);
}

利用反射获取类的实例,创建对象并调用方法

public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, IOException, ClassNotFoundException, InstantiationException {
    // 使用反射机制,根据字符串获得 Class 对象
    Class<?> c = Class.forName(getName("className"));
    System.out.println(c.getSimpleName());
    // 获取方法
    Method method = c.getDeclaredMethod(getName("methodName"));
    // 绕过安全检查
    method.setAccessible(true);
    // 创建实例对象
    TestInvoke testInvoke = (TestInvoke)c.newInstance();
    // 调用方法
    method.invoke(testInvoke);
}
运行结果

TestInvoke

I am fine

通过上述代码,我们展示了如何使用反射机制动态加载类、创建实例、并调用方法,这在实际开发中非常有用。