反射在代码和框架中的应用场景
加载数据库驱动
在开发中,我们有时需要根据实际情况动态加载不同的数据库驱动。例如,项目的底层数据库有时使用 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 的过程如下:
- 将所有 XML 或 properties 配置文件加载入内存。
- 解析 XML 或 properties 文件内容,获取实体类的字节码字符串及相关属性信息。
- 使用反射机制,根据字符串获取某个类的
Class实例。 - 动态配置实例的属性。
示例
配置文件
在 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
通过上述代码,我们展示了如何使用反射机制动态加载类、创建实例、并调用方法,这在实际开发中非常有用。