Java反射及 IoC原理、内省机制
JAVA反射及IoC原理、JAVA内省
1. 反射
反射是框架设计的灵魂,使用前提:必须先得到代表的字节码的Class,Class类用于表示.class文件(字节码文件)。
1.1 反射概述
主要指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。
Java反射机制:在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性。
1.2 反射机制的作用
- 在运行时判断任意一个对象所属的类
- 在运行时获取类的对象
- 在运行时访问java对象的属性,方法,构造方法等
1.3 反射机制的优缺点
- 优点:运行时确定类型,再绑定(创建)对象,体现多态性,可降低类之间的耦合性。
- 缺点:对性能有一定影响,使用反射可认为一种解释操作,告诉JVM想要进行何种操作,这类操作总是慢于直接执行相同的操作(如直接创建(new)对象)。
1.4 反射的使用
- 获取Class对象
- 获取类的构造方法
- 获取类的成员变量
- 获取类的成员方法
1.4.1 获取Class对象
package Reflect;/*示例类Reflect.Domo,以下例子均用该类*/class Demo{private String name;public Demo(){}public Demo(String name){this.name = name;}public String getName(){return name;}public void setName(String name){this.name = name;}@overridepublic String toString(){return "["+this.name+"]";}private String show(String name){return name;}}
/***获取Class对象的三种方法*1. Object-->getClass()方法;*2. 任何数据类型(包括基本数据类型)都有一个“静态”的class属性*3. 通过Class类的静态方法:forName(String className);*4. 一般采用第三种方式获取*/class Hello{public static void main(String[] args){Class<?> demo = null;demo = class.forName("Reflect.Domo");System.out.println("demo.getName()");}}//[运行结果]:Reflect.Demo
/***通过Class实例化其他类的对象*经过以上步骤获取了一个Demo类的Class实例*/class Hello{public static void main(String[] args){Class<?> demo = null;demo = class.forName("Reflect.Demo");Demo d = null;d = (Demo)d.newInstance();d.setName("leo");System.out.println(d);}}//[运行结果]:[leo]
注:
- 在运行期间,一个类,只有一个Class对象产生
- 若需要反射的类只定义了一个有参数的构造函数之后,会出现错误,即使用不到,也应该编写一个无参的构造函数
1.4.2 获取类的构造方法
class Hello{public static void main(String[] args){Class<?> demo = null;demo = class.forName("Reflect.Domo");//取得全部构造函数Constructor<?> cons[] = demo.getConstructors();Demo d1 = null;Demo d2 = null;d1 = cons[0].newInstance();d2 = cons[1].newInstance("leo");}}//[运行结果]://[null]//[leo]
1.4.3 获取类的成员变量
/***获取类的成员变量并调用*1. 批量的*1.1) Field[] getFields():获取所有的“公有字段”*1.2) Field[] getDeclareFields():获取所有的字段,包括:私有、受保护、默认、公有*2. 获取单个的*2.1) public Field getField(String fieldName):获取某个公有字段*2.2) public Field getDeclaredField(String fieldName):获取某个字段(可以是私有的)***设置字段的值*Field-->public void set(Object obj, object value)*参数说明:*1.obj:要设置的字段所在的对象*2.value:要为字段设置的值*/class Hello{public static void main(String[] args){Class<?> demo = null;demo = class.forName("Reflect.Domo");//获取字段Field[] fieldArray = demo.getFields();for(Field f:fieldArray){System.out.println(f);}//获取公有字段并调用,假设Demo类的name字段为公有Field f = demo.getField("name");System.out.println(f);//获取对象并为对象内字段设置值Demo d = (Demo)demo.getConstructor().newInstance();f.set(d,"leo");}}
1.4.4 获取类的成员方法
/***获取类的成员变量并调用*1. 批量的*1.1) public Method[] getMethods():获取所有公有方法(包含父类的方法也包含Object类)*1.2) public Method[] getDeclareMethods():获取所有的成员方法,包括私有的(不包括继承的)*2. 获取单个的*2.1) public Method getMethod(String name,Class<?>...parameterTypes):*参数说明:*name:方法名*Class...:形参的Class类型对象*2.2) public Method getDeclareMethod(String name,Class<?>...parameterTypes)***调用方法:*Method-->puvlic Object invoke(Object obj,Object...args)*参数说明:*obj:要调用方法的对象*args:调用方式时所传递的实参**/class Hello{public static void main(String[] args){Class<?> demo = null;demo = class.forName("Reflect.Domo");//获取所有共有方法Method[] methodArray = demo.getMethods();for(Method m:methodArray){System.out.println(m);}//获取公有的toString()方法Method m = demo.getMethod("toString",String.class);System.out.println(m);//获取私有的show()方法m = demo.getDeclareMethod("show",String.class);m.setAccessible(true); //解除私有限定//获取一个对象Demo d = demo.getConstructor().newInstance();Object result = m.invoke(d,"Yooo");System.out.println("["+result+"]")//[运行结果]:Yooo}}
1.5 IoC原理
Ssoring中的IoC的实现原理就是工厂模式加反射机制。
1.不使用反射机制的工厂模式
/***工厂模式*/interface fruit{public abstract void eat();}class Apple implements fruit{public void eat(){System.out.println("Apple");}}class Orange implements fruit{public void eat(){System.out.println("Orange");}}// 构造工厂类// 也就是说以后如果我们在添加其他的实例的时候只需要修改工厂类就行了class Factory{public static fruit getInstance(String fruitName){fruit f=null;if("Apple".equals(fruitName)){f=new Apple();}if("Orange".equals(fruitName)){f=new Orange();}return f;}}class hello{public static void main(String[] a){fruit f=Factory.getInstance("Orange");f.eat();}}
当我们在添加一个子类的时候,就需要修改工厂类了。如果我们添加太多的子类的时候,改的就会很多。
2.利用反射机制的工厂模式
package Reflect;interface fruit{public abstract void eat();}class Apple implements fruit{public void eat(){System.out.println("Apple");}}class Orange implements fruit{public void eat(){System.out.println("Orange");}}class Factory{public static fruit getInstance(String ClassName){fruit f=null;try{f=(fruit)Class.forName(ClassName).newInstance();}catch (Exception e) {e.printStackTrace();}return f;}}class hello{public static void main(String[] a){fruit f=Factory.getInstance("Reflect.Apple");if(f!=null){f.eat();}}}
现在就算我们添加任意多个子类的时候,工厂类就不需要修改。
使用反射机制的工厂模式可以通过反射取得接口的实例,但是需要传入完整的包和类名。而且用户也无法知道一个接口有多少个可以使用的子类,所以我们通过属性文件的形式配置所需要的子类。
3.使用反射机制并结合属性文件的工厂模式(即IoC)
先创建一个fruit.properties的资源文件
apple=Reflect.Appleorange=Reflect.Orange
然后编写主类代码
package Reflect;import java.io.*;import java.util.*;interface fruit{public abstract void eat();}class Apple implements fruit{public void eat(){System.out.println("Apple");}}class Orange implements fruit{public void eat(){System.out.println("Orange");}}//操作属性文件类class init{public static Properties getPro() throws FileNotFoundException, IOException{Properties pro=new Properties();File f=new File("fruit.properties");if(f.exists()){pro.load(new FileInputStream(f));}else{pro.setProperty("apple", "Reflect.Apple");pro.setProperty("orange", "Reflect.Orange");pro.store(new FileOutputStream(f), "FRUIT CLASS");}return pro;}}class Factory{public static fruit getInstance(String ClassName){fruit f=null;try{f=(fruit)Class.forName(ClassName).newInstance();}catch (Exception e) {e.printStackTrace();}return f;}}class hello{public static void main(String[] a) throws FileNotFoundException, IOException{Properties pro=init.getPro();fruit f=Factory.getInstance(pro.getProperty("apple"));if(f!=null){f.eat();}}}//[运行结果]:Apple
2. 内省
2.1 内省概述
可参看本页#3.1反射和内省的区别#。
在Java内省中,用到以上及各类。通过BeanInfo这个类可以获取到类中方法和属性。即通过类Introspector的getBeanInfo方法获取某个对象的BeanInfo信息,然后通过BeanInfo来获取属性的描述器(PropertyDescriptor),通过这个属性描述器可以获取某个属性对应的Getter/Setter方法,然后我们可以通过反射机制在调用这些方法,即为内省机制。
2.2 JDK内省类库
- java.beans.Introspector:Introspector 类为通过工具学习有关受目标 Java Bean 支持的属性、事件和方法的知识提供了一个标准方法。
- java.beans.BeanInfo接口:希望提供有关其 bean 的显式信息的 bean 实现者可以提供某个 BeanInfo 类,该类实现此 BeanInfo 接口并提供有关其 bean 的方法、属性、事件等显式信息。
- java.beans.PropertyDescriptor:PropertyDescriptor 描述 Java Bean 通过一对存储器方法导出的一个属性。
2.3 内省类库测试代码示例
//被测类public class User{private String name;public String getName(){return name}public void setName(String name){this.name = name;}}public class IntrospectorTest {private User user ;public void init() {user = new User() ;user.setName("张三") ;}public void getBeanPropertyInfo() throws Exception {//获取User-BeanInfo对象:beanInfo是对一个Bean的描述,可以通过它取得Bean内部的信息/***获取User-BeanInfo对象*1.Introspector类* 是一个工具类,提供了一系列取得BeanInfo的方法;*2.BeanInfo接口* 对一个JavaBean的描述,可以通过它取得Bean内部的信息;*3.PropertyDescriptor属性描述器类* 对一个Bean属性的描述,它提供了一系列对Bean属性进行操作的方法*/BeanInfo userBeanInfo = Introspector.getBeanInfo(User.class) ;PropertyDescriptor[] pds = userBeanInfo.getPropertyDescriptors() ;for (PropertyDescriptor pd : pds) {Method method = pd.getReadMethod() ;String methodName = method.getName() ;Object result = method.invoke(user) ;System.out.println(methodName + "-->" + result);}}public void getBeanPropertyByName() throws Exception {//获取name属性的属性描述器PropertyDescriptor pd = new PropertyDescriptor("name", user.getClass()) ;//得到name属性的getter方法Method readMethod = pd.getReadMethod() ;//执行getter方法,获取返回值,即name属性的值String result = (String) readMethod.invoke(user) ;System.out.println("user.name" + "-->" + result);//得到name属性的setter方法Method writeMethod = pd.getWriteMethod() ;//执行setter方法,修改name属性的值writeMethod.invoke(user, "李四") ;System.out.println("user.name" + "-->" + user.getName());}}
总结:内省操作非常繁琐,所以Apache开发了一套简单、易用的API来操作Bean属性——BeanUtils工具包。
3. 反射和内省的区别
反射
反射就是Java运行状态吧Java类中的各种成分映射成相应的Java类,可以动态地获取所有的属性以及动态调用任意一个方法(包括成员变量、成员方法、构造器等),强调的是运行状态。
内省
内省(IntroSpector)是Java语言对Bean类属性、事件的一种缺省处理方法。
JavaBean:一种特殊的类,用于传递数据信息,这种类的方法主要用于访问私有的字段,切方法名符合某种命名规则,即Getter和Setter方法。用于两个模块之间传递信息的JavaBean称为“值对象”(Value Object,"VO")。
内省机制通过反射来实现,用来暴露一个Bean的属性、方法和事件。
转载于:https://blog.51cto.com/13801495/2130813
Java反射及 IoC原理、内省机制相关推荐
- java 内省机制_Java反射及 IoC原理、内省机制
JAVA反射及IoC原理.JAVA内省 1. 反射反射是框架设计的灵魂,使用前提:必须先得到代表的字节码的Class,Class类用于表示.class文件(字节码文件). 1.1 反射概述主要指程序可 ...
- 彻底搞懂java反射技术及其原理
概述:反射是java中最强大的技术之一,很多高级框架都用到了反射技术,面试中也是经常问的点,所以搞懂反射非常重要! 文章目录 1.反射是什么? 2.反射的底层原理 3.三种方式获取Class对象 4. ...
- Java反射的底层原理,以及Java反射的性能分析及优化
java的反射技术,号称是编程界的九阳神功,也可以说是框架的灵魂.也正是这种反射机制使静态语言的java具备了动态语言的某些特质.就是有了反射,才让java动态,编程的时候更加灵活,能够动态获取信息以 ...
- 浅谈Java反射的实现原理
从一段示例代码开始 Class clz = Class.forName("ClassA");Object instance = clz.newInstance();Method m ...
- 【转】java线程池的原理和机制
这几天主要是狂看源程序,在弥补了一些以前知识空白的同时,也学会了不少新的知识(比如 NIO),或者称为新技术吧. 线程池就是其中之一,一提到线程,我们会想到以前<操作系统>的生产者与消费者 ...
- 【重难点】【Java基础 05】说一说你平时遇到的异常、什么情景下会用到反射、反射的底层原理
[重难点][Java基础 05]说一说你平时遇到的异常.什么情景下会用到反射.反射的底层原理 文章目录 [重难点][Java基础 05]说一说你平时遇到的异常.什么情景下会用到反射.反射的底层原理 一 ...
- Java基础——Java反射机制及IoC原理
一.概念 主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义.在java中,只要给定类的名字, 那么就可以通过反射机制 ...
- 解析Spring IOC原理——工厂模式与反射机制的综合应用
(一)工厂模式 从一个例子开始讲起: 首先我们建立一个Chinese.java类,该类的sayHelloWorld(String name)方法,用中文对名为name的人问好,其内容如下: [java ...
- java反射机制(三)---java的反射和代理实现IOC模式 模拟spring
IOC(Inverse of Control)可翻译为"控制反转",但大多数人都习惯将它称为"依赖注入".在Spring中,通过IOC可以将实现类.参数信息等配 ...
最新文章
- 机器学习中的数学意义
- 解答关于学习前端的一些问题
- python条形图数据标签_python – Plotly中用于条形图的单独标记条形图
- 阿里百度12个iOS 技术面试题及答案总结,希望对你有帮助!
- unity加载sprite_Unity 分离贴图 alpha 通道实践
- docker 进入容器 开启一个新的bash窗口
- 我的世界java多大内存_我的世界电脑版内存多大
- 教育部正式宣布:9年义务教育大变动!与孩子息息相关
- python控制结构是,python 程序控制结构
- java基础知识总结(经典)_Java基础知识总结(超级经典)(三)
- python中输入多个值用什么符号隔开_字典中多个元素之间使用
- 【阅读笔记】项亮前辈的《推荐系统实战》
- 这些是 Python 官方推荐的最好书籍(推荐)
- Linux 最大文件名
- 考研英语 - word-list-37
- 中文编程书籍资料一览表
- vim只读模式修改文件
- Mac电脑如何启用root用户
- Python大型网络爬虫项目开发实战
- UVA 1626括号序列DP