# 概述
反射非常強大,但是學習了之后,會不知道該如何使用,反而覺得還不如直接調用方法來的直接和方便。
> 打個比方,整個項目非常大,如果改代碼,編譯打包,需要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);
}
}
```