实现一个“框架”,在不改变该类的任何代码的前提下,实现创建任意类的对象,并执行其中的任意方法。
阅读之前如果对反射不太了解可以先阅读:Java反射基础篇<简单原理和常用API的使用>
一、先定义两个简单的类
简单的不能再简单的两个类
一个男孩
public class Boy {
public void play() {
System.out.println("男孩正在打篮球····");
}
}
一个女孩
public class Girl {
public void sing() {
System.out.println("女孩正在唱歌····");
}
}
二、直接new有什么弊端
常规的我们去实现boy中的方法,和去切换实现girl中的方法的时候,会直接new,然后修改代码去实现
public class NewTest {
public static void main(String[] args) {
Boy boy = new Boy();
boy.play();
// Girl girl = new Girl();
// girl.sing();
}
}
“弊端”就是需要改代码,重新打包,发包,测试,上线…
三、大致实现的思路
我们需要实现的是在不改变任何的代码的前提下,实现切换Boy–>Girl,并执行对应的方法。这里我们大致实现的思路如下:
四、实例说明
先在src目录下定义一个frame.properties文件如下
根据上述实现的思路进行代码实现如下所示
public class FrameTest {
public static void main(String[] args) throws Exception {
// 第1步:加载配置文件和数据
// 1.1 java万物皆对象,Properties也有对应的对象,创建Properties对象
Properties properties = new Properties();
// 1.2 获取本类的classLoader,用以可以找到frame.properties
ClassLoader classLoader = FrameTest.class.getClassLoader();
// 1.3 读取frame.properties文件
InputStream in = classLoader.getResourceAsStream("frame.properties");
// 1.4 加载进Properties对象之中
properties.load(in);
// 1.5 获取配置文件中的定义的数据
String className = properties.getProperty("className");
String methodName = properties.getProperty("methodName");
// 第2步:加载该类进内存
Class cls = Class.forName(className);
// 第3步:创建对象
Object obj = cls.newInstance();
// 第4步:获取方法对象
Method method = cls.getMethod(methodName);
// 第5步:执行方法
method.invoke(obj);
}
}
第1步,加载配置文件和数据,这个其实不是本篇的重点,大致就是需要找到配置文件并能获取类名和方法名即可。
执行代码,如下所示,正确的执行了boy中的代码
如果想要实现执行Girl中的sing()方法,只需要修改位置文件为
className=reflect.frame.Girl
methodName=sing
即可实现执行Girl中的代码
五、小结
和直接new相比,一个是需要改代码,一个是改配置文件,这两者有什么区别?当后续系统比较复杂之后,改配置文件可以避免重复打包,发包,测试,上线…,一个好的框架可以极大的减少开发和运维的工作量,比如Spring。
未完待续,后续会继续基于此篇,结合配置文件+工厂模式+反射,实现一个完整版的Dependency Injection依赖注入框架,这也及就是Spring框架实现的雏形。