参考
https://china-jianchen.iteye.com/blog/728774
https://baijiahao.baidu.com/s?id=1573298089973615&wfr=spider&for=pc
https://blog.csdn.net/carson_ho/article/details/80921333
Gitee代码
https://gitee.com/fysola/java_core/tree/master/Java_reflect
https://gitee.com/fysola/java_core/tree/master/Java_reflection_enhancement_for_factory_method_pattern
概念
摘自百度:
反射:程序在运行状态中,可以动态加载一个只有名称的类,加载完类之后,在堆内存中,就产生了一个 Class 类型的对象,这个对象就包含了完整的结构信息,通过这个对象我们可以看到类的结构。这个对象就像一面镜子,所以我们形象的称之为——反射。
实现原理
JVM加载xxx.class字节码后,会生成一个Class实例,这个实例用来描述xxxx.class的元数据,比如有哪些构造方法,有哪些成员变量,有哪些成员方法等。
java.lang.reflect包提供了一些方法能够访问xxx.class的Class信息,从而实现在程序运行时,动态创建xxx.class的实例对象,并调用其方法。
常用API (Class, Constructor, Field, Method四个类)
java.lang.Class类——获取Class实例,创建class实例
- 静态方法 forName()
用来获取xxx.class对应Class实例,
例如 Class clz = Class.forName("com.zhenai.api.Apple");
- 成员方法 newInstance()
用来创建类实例,只能用默认构造函数初始化对象
- 成员方法 getFields()
获取class对象public成员变量
- 成员方法 getDeclaredFields()
能获取公有和私有成员变量
java.lang.reflect.Constructor类——创建并初始化class实例
- 成员方法 newInstance()
创建,并初始化一个class对象,可以传入参数
例如Constructor appleConstructor = clz.getConstructor();
Object appleObj = appleConstructor.newInstance();
java.lang.reflect.Field类——获取成员变量信息
java.lang.reflect.Method类——获取成员方法信息
例如
Method setPriceMethod = clz.getMethod("setPrice", int.class);
setPriceMethod.invoke(appleObj, 14); //invoke()是反射中使用频率非常高的方法
注:获取Class实例方式
获取一个class对象对应的Class实例有三种方式
方法一:
调用类自己的静态属性 .class
Class<?> class = ClassName.class;
方法二
调用object.getClass()
Class<?> class = object.getClass();
方法三
通过反射 Class<?> class = Class.forName("类名全路径")
应用场景
工厂模式优化(手写spring框架)
简述简单工厂模式
伪代码
class Factory {
Factory( type ) {
case type1 : new product1;
case type2 : new product2;
...
}
}
main() {
Factory factory = new Factory()
factory( type1 ).commonFunction();
factory( type2 ).commonFunction();
}
其核心思想是所有对象类型的创建都集中在工厂Factory中,外部通过传入不同参数来创建不同对象,并调用共同方法(基于接口)。
简单工厂模式有个严重缺陷就是一旦要修改/增减某个产品类product,就必须修改工厂类。
优化简单工厂类(Spring框架原理)
伪代码
class Factory {
static Product getInstance(string classname) {
Product p = null;
//通过反射动态创建产品对象
Class product_class = Class.forName(className);
p = product_Class.newInstance();
return p;
}
}
main(){
Factory factory = new Factory();
factory.getInstance( Property("ProductA") ).commonFunction();
factory.getInstance( Property("ProductB") ).commonFunction();
}
//上面的productA和productB则可以在配置文件中自由配置
ProductA = com.demo.product1
ProductB = com.demo.product2
改进后的工厂模式优势明显,当需要修改配置的产品类型时,只需要修改配置文件,当要增减产品类型时,也不再需要修改工厂类,只需要修改业务调用模块即可,真正实现热拔插。