反射是为了解决在运行期,对某个实例一无所知的情况下,如何调用其方法。利用java的反射机制可以很方便的对一个类进行各种操作,也是一个“框架”所依赖的核心功能之一。
下面利用反射来完成一个“基础框架“的搭建,这个框架可以根据配置文件中配置的类路径去操作对应的类,那么每次运行就不需要修改java程序,只需要修改配置文件即可。
框架功能:通过用户在配置文件设置的姓名和年龄来判断用户是否成年。
1.创建一个用户类User,放在包reflex.FrameDemo下(简洁起见,就没有添加getter和setter)
package reflex.FrameDemo;
public class User {
protected String name;
protected String password;
protected int age;
//自定义方法,判断是否成年(age>18)
public String Adule(){
if( age >= 18) return "该用户已成年";
else return "该用户未成年";
}
public User() {
}
public User(String name, String password,int age) {
this.name = name;
this.password = password;
this.age = age;
}
}
2.创建一个properties配置文件myConfig.properties,配置文件我这里也是放在类文件的同一个包下(reflex.FrameDemo)
#指定一个要使用的类的路径
myClassName=reflex.FrameDemo.User
#指定要操作的方法
myMethodName=Adule
#指定要传入的参数
name=张三
age=16
3.创建一个”框架“类,用来实现指定的功能也在同一个包下(reflex.FrameDemo)
package reflex.FrameDemo;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Properties;
public class MyFrame {
public static void main(String[] args) throws Exception {
//1 加载配置文件
//1.1 创建Properties对象,用于处理properties文件
Properties myproperties = new Properties();
//1.2 通过类加载器获取当前这个框架类的类加载对象
ClassLoader myclassLoader = MyFrame.class.getClassLoader();
//1.3 通过当前类的类加载对象的getResourceAsStream可以通过文件名扫描并获取当前类所在src根目录下面的文件
//这里以字符流的形式获取配置文件
//InputStream inputStream = myclassLoader.getResourceAsStream("reflex/FrameDemo/myConfig.properties");
//InputStreamReader myPropertiesStrem = new InputStreamReader(inputStream);
//注意,通过类加载器只能获取在src目录下面的文件,如果和类名在同一个包中,直接用类对象的getResourceAsStream即可
//我这里为了简洁,就放在同一个包下,所以1.2和1.3可以省略
InputStream inputStream = MyFrame.class.getResourceAsStream("myConfig.properties") ;//获取字节流
InputStreamReader myPropertiesStrem = new InputStreamReader(inputStream);//转换为字符流
//1.4 将找到的配置文件加载到Properties对象中
myproperties.load(myPropertiesStrem);
//1.5获取配置文件中定义的数据(注意读取的为String类型,要转化为int类型)
String className = myproperties.getProperty("myClassName");
String methodName = myproperties.getProperty("myMethodName");
String name = myproperties.getProperty("name");
int age = Integer.parseInt(myproperties.getProperty("age"));
//2 通过配置文件数据操作类
//2.1 通过配置文件的数据将对应的类加载到内存
Class myclass = Class.forName(className);
//2.2 通过内存中的class对象(字节码文件)执行构造方法赋值
//获取赋值的构造方法对象
Constructor constructor = myclass.getConstructor(String.class,int.class);
//执行该构造方法来创建一个类的实例
Object myClassObj = constructor.newInstance(name,age);
//2.3 通过内存中的class对象(字节码文件)去执行成员方法
//获取成员方法对象
Method myMehtod = myclass.getDeclaredMethod(methodName);
//执行该方法,并将结果打印
System.out.println(myMehtod.invoke(myClassObj));
}
}
这样做的好处就是,我们只需要修改配置文件,而不用修改任何java代码就可以实现不同的输入。
当age=16时,输出如下:
到此就完成了一个基础半成品框架的制作