# 概述
反射非常强大,但是学习了之后,会不知道该如何使用,反而觉得还不如直接调用方法来的直接和方便。
> 打个比方,整个项目非常大,如果改代码,编译打包,需要1个小时。
这个时候,比如天猫线上的服务器出问题了,你是希望改代码,编译打包,重启,花一个小时呢? 还是 不用改代码编译,只需要改txt 就重启?
这就是配置文件,比配置写死在代码里的优点
代码要写"活", 不能写"死",这也是解耦的思想。反观许多的框架思想,也是这样通过修改配置文件的方式来开发。
# 业务类
首先准备两个业务类,这两个业务类很简单,就是各自都有一个业务方法,分别打印不同的字符串
Service1 :
```
package com.dodoke.reflection;
public class Service1 {
public void doService1() {
System.out.println("业务方法1");
}
}
```
Service2:
```
package com.dodoke.reflection;
public class Service2 {
public void doService2(){
System.out.println("业务方法2");
}
}
```
# 非反射方式
当需要从第一个业务方法切换到第二个业务方法的时候,使用非反射方式,必须修改代码,并且重新编译运行,才可以达到效果
```
package com.dodoke.util;
import com.dodoke.reflection.Service1;
import com.dodoke.reflection.Service2;
public class Test {
public static void main(String[] args) {
// new Service1().doService1();
new Service2().doService2();
}
}
```
# 反射方式
使用反射方式,首先准备一个配置文件,就叫做spring.txt吧, 放在src目录下。 里面存放的是类的名称,和要调用的方法名。
在测试类Test中,首先取出类名称和方法名,然后通过反射去调用这个方法。
当需要从调用第一个业务方法,切换到调用第二个业务方法的时候,不需要修改一行代码,也不需要重新编译,只需要修改配置文件spring.txt,再运行即可。
这也是**Spring框架**的最基本的原理,只是它做的更丰富,安全,健壮。
spring.txt:
```
class=com.dodoke.reflection.Service1
method=doService1
```
测试类:
```
package com.dodoke.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Properties;
public class Test2 {
@SuppressWarnings({ "rawtypes", "unchecked" })
public static void main(String[] args) throws Exception {
// 从spring.txt中获取类名称和方法名称
File springConfigFile = new File("D:/TestPrcWorkSpace/java_advanced/src/spring.txt");
Properties springConfig = new Properties();
springConfig.load(new FileInputStream(springConfigFile));
String className = (String) springConfig.get("class");
String methodName = (String) springConfig.get("method");
// 根据类名称获取类对象
Class clazz = Class.forName(className);
// 根据方法名称,获取方法对象
Method m = clazz.getMethod(methodName);
// 获取构造器
Constructor c = clazz.getConstructor();
// 根据构造器,实例化出对象
Object service = c.newInstance();
// 调用对象的指定方法
m.invoke(service);
}
}
```