`

反射机制与系统耦合实力详解

阅读更多
反映射技术(以下简称:反射)的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用。最近,反射机制也被应用到了视窗系统、操作系统和文件系统中。
在如今程序语言的设计领域中,几乎每种OO语言都专门设计了支持反射技术的API,不管是Microsoft公司的.Net框架还是SUN公司的Java语言都是如此,本技术帖就以Java为例来进行探讨。
在Java编程语言中,反射是一种强大的工具。它使您能够创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代码链接。这样一来整个系统的耦合性就会降低并可以大大增加系统的灵活度。反射机制被大量运用在系统架构的设计层次上,并且在编写公共类和系统基盘的时候也起到了举足轻重的作用,甚至有人提出这门技术是一个程序员转型成为系统架构师的必经之路。
反射机制是 Java 被视为动态(或准动态)语言的关键,允许程序于执行期取得任何已知名称之 class 的內部信息,包括 包、父类、接口、内部, outer class, fields、constructors、methods、modifiers,並可于执行期生成实体、变更 fields 內容或唤起 methods。
有了反射机制,我们可以:
1.判断某个对象所属的类型(Class)。
2.取得类型(Class)的属性,方法,构造体和父类的相关信息。
3.找出接口中的常量和方法定义。
4.为一个执行期才得知名称的类产生对象。
Java类反射中的主要方法:
对于类而言构造函数、字段和方法是最为重要的内容java.lang.Class 提供四种独立的反射调用,以不同的方式来获得信息。调用都遵循一种标准格式。
以下是用于查找构造函数的一组反射调用:
方法
说明
Constructor getConstructor(Class[] params)
获得使用特殊的参数类型的
公共构造函数
Constructor[] getConstructors()
获得类的所有公共构造函数
Constructor getDeclaredConstructor(Class[] params)
获得使用特定参数类型的构造函数(与访问级别无关)
Constructor[] getDeclaredConstructors()
获得类的所有构造函数(与访问级别无关)
获得字段信息的Class 反射调用不同于那些用于接入构造函数的调用,在参数类型数组中使用了字段名:
方法
说明
Field getField(String name)
获得指定的公共字段
Field[] getFields()
获得类的所有公共字段
Field getDeclaredField(String name)
获得指定的字段
Field[] getDeclaredFields()
获得类声明的所有字段
用于获得方法信息函数:
方法
说明
Method getMethod(String name, Class[] params)
使用特定的参数类型,获得命名的公共方法
Method[] getMethods()
获得类的所有公共方法
Method getDeclaredMethod(String name, Class[] params)
使用特定的参数类型,获得类声明的命名的方法
Method[] getDeclaredMethods()
获得类声明的所有方法
开始使用反射机制:
用于反射机制的类,如 Method,可以在 java.lang.relfect 包中找到。使用这些类的时候必须要遵循三个步骤:第一步是获得你想操作的类的java.lang.Class 对象。在运行中的 Java 程序中,用 java.lang.Class 类来描述类和接口等。
下面就是获得一个 Class 对象的方法之一:
Class c = Class.forName ("java.lang.Integer");
这条语句得到一个 String 类的类对象。还有另一种方法,如下面的语句:
Class c = Integer.class;
或者
Class c = Integer.TYPE;
它们可获得基本类型的类信息。其中后一种方法中访问的是基本类型的封装类 ( Integer) 中预先定义好的 TYPE 字段。
第二步是调用诸如 getDeclaredMethods 的方法,以取得该类中定义的所有方法的列表。
一旦取得这个信息,就可以进行第三步了。
第三步是使用 reflection API 来操作这些信息,如下面这段代码:

Class c = Class.forName("java.lang.String");
Method m[] = c.getDeclaredMethods();
System.out.println(m[0].toString());


它将以文本方式打印出 String 中定义的第一个方法的原型。
反射经常由框架型代码使用,由于这一点,我们可能希望框架能够全面接入代码,无需考虑常规的接入限制。例如当代码在不值得信任的代码共享的环境中运行时。
假设有以下这个类的声明:

class DemoReflection
{
private String name = null;
private void doPrint() {
System.out.println("print.....");
}
};

可以肯定的是,这个类中的属性name和方法doPrint都是无法对外展示的,但是使用了反射以后就可以办到。

package cn.softworks.demo;
import java.lang.reflect.*;
publicclass TestReflection {
publicstaticvoid main(String args[]) {
try {
// 通过反映射技术得到DemoReflection的类型
Class cls = Class.forName("DemoReflection");
// 动态创建DemoReflection类的实力
Object instance = cls.newInstance();
// 通过反映射技术得到DemoReflection的非公有方法doPrint
Method m = cls.getDeclaredMethod("doPrint",
new Class[] { String.class });
// 表示可以随意访问该类中的方法
m.setAccessible(true);
// 调用doPrint方法
m.invoke(instance, new Object[] { "Softworks" });
} catch (Exception ex) {
System.out.println(ex);
}
}
};

在该代码中,读者可能看到了一个比较陌生的方法setAccessible,这个方法非常重要,如果它不被设置成true那么所有非公有方法仍然无法调用,所以学员在调用非公有方法的时候需要注意这点。
Private属性的访问方式和方法的访问方式类似:
反射的实际应用
在之前的介绍中,我们已经了解了反射机制的重要性,也已经了解到了反射经常被运用到系统框架设计和系统解耦中,现在就以一个真实的项目开发案例来探讨一下反射机制的重要性。
1.什么叫系统耦合:
或许很少有读者会在电影结束后做在电影院中观看电影的幕后工作者,但是可以肯定的是,如果没有那么多幕后工作者,那么就不会有诸如《指环王》等大片的出现了。但是如果真的要拍摄出像《指环王》这样的大片,光依靠强大的拍摄团队还不够,团队中的每个成员都必须要相互合作和交流,那么这种行为就被称为团队人员和团队人员的耦合关系。
软件系统就如同刚才的电影拍摄团队,是有大量的类(工作人员)所组成的,那么这些类之间如果没有交互的话,整个软件系统就不可能正确合理的工作,因此软件系统中的耦合就来自于类与类之间的通讯,例如以下代码:

Cleaner clearner = new Cleaner(“Chen.yu”);
Broom broom = new Broom();
cleaner.clear(broom);

通过这段代码,我们可以看出,Cleaner类和Broom之间有相互交互的关系,也就是说这两个类之间产生了耦合关系。 耦合关系的存在使的系统的开发者只能实现“串行式开发”,也就是说刚才的代码如果有一个人来开发的话,耦合关系是不会影响到系统开发了。但是如果
Cleaner类和Broom类有两个人分别开发的话,那么问题就暴露出来了。
通过代码我们可以得出结论,要想开发Cleaner类就必须先开发Broom类,因为Cleaner类中的方法clear需要使用Broom类的信息。如何让来使两个原本具有耦合关系的类,变的没有耦合关系呢?
2.利用工厂模式解决耦合关系:
现在我把代码改写成以下的状态:

package cn.softworks.test;
import cn.softworks.demo.BeanFactory;
import cn.softworks.demo.Cleaner;
import cn.softworks.demo.IClearEquipment;
/**
*反射机制的测试类
*
*@version1.0
*
*@authorChen.yu
*
*上海Softworks对日软件人才培训中心版权所有
*/
publicclass TestClient {
publicstaticvoid main(String args[]) {
//通过工厂创建指定的清洁工具类
IClearEquipment eq =
(IClearEquipment) BeanFactory.newInstance().creator("ClearEquipment");
if(eq == null)
return;
//创建清洁工对象
Cleaner cleaner = new Cleaner();
//清洁工人开始清洁
cleaner.clear(eq);
}
}
代码虽然多了,但是可以肯定的我们只使用了Cleaner类并没有使用到Broom类,那么Broom类上哪里去了呢?我们看到了IClearEquipment接口,Broom类正好实现了该接口,并且我们利用工厂模式BeanFactory完全隐藏了Broom类的创建细节,以此来解决Broom类与Cleaner类之间的耦合关系,现在Broom类和Cleaner类就可以交给2个开发员并行开发了。

以下是IClearEquipment接口的代码片断:

package cn.softworks.demo;
/**
*
*该接口是的作用是用来定义清洁设备的标准<br>
*换句话说,如果要想成为清洁设备,那么就必须要具有清洁能力
*
*@version1.0
*
*@authorChen.yu
*
*上海Softworks对日软件人才培训中心版权所有
*/
publicinterface IClearEquipment {
/**
*清洁设备的清洁方法<br>
*不同的清洁设备有不同的清洁方法
*
*/
publicvoid clear();
}

以下是BeanFactory类的代码片断:

package cn.softworks.demo;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
/**
*该类的作用是从配置文件中读取类名,并依靠反射将指定类的实体<br>
*返回,以此达到“清洁工”类和“清洁设备”类之间的解耦<br>
*
*该类被设置成了单例模式,并在创建指定类的时候加入了同步锁,<br>
*以此保证线程安全。
*
*@version1.0
*
*@authorChen.yu
*
*上海Softworks对日软件人才培训中心版权所有
*/
publicclass BeanFactory {
/**
*单例工厂实体
*/
privatestatic BeanFactory instance = null;
/**
*用于保存softworks.cfg.properties配置文件的实体。
*/
privatestatic Properties config = null;
/**
*默认配置文件路径
*/
privatestaticfinal String CONFIG_PATH = "softworks.cfg.properties";

/**
*使用了单例模式的工厂类默认构造函数
*
*/
private BeanFactory() {
//得到配置文件的路径
InputStream stream = Thread.currentThread().getContextClassLoader()
.getResourceAsStream(CONFIG_PATH);
config = new Properties();
try {
//将配置文件信息加载到config对象中
config.load(stream);
} catch (IOException e) {
instance = null;
}
}
/**
*创建BeanFactory实体的静态方法
*
*@returnBeanFactory的单例实体
*/
publicsynchronizedstatic BeanFactory newInstance() {
//判断BeanFactory的实体是否已经存在
if (instance != null)
returninstance;
//如果BeanFactory实体不存在那么立刻创建
instance = new BeanFactory();
returninstance;
}

/**
*工厂了的创建方法,该方法可以用于创建配置文件中指定key名的类<br>
*现在配置文件中有如下信息:<br>
*ClearEquipment=cn.softworks.demo.DustCollector<br>
*那么当参数被设置成ClearEquipment的时候,通过该方法就会创建<br>
*cn.softworks.demo.DustCollector类的实体。
*
*@paramkey配置文件中类所对应的Key名
*
*@return 被加载类的实体
*/
publicsynchronized Object creator(String key) {
if(config == null)
returnnull;
//得到配置文件中的类名
String className = config.getProperty(key);
try {
//通过反射机制创建类实体
return Class.forName(className).newInstance();
} catch (Exception e) {
returnnull;
}
}
}

以下是Broom类的代码片断:

package cn.softworks.demo;
/**
*该类是用来描述扫帚这个清洁工具的<br>
*它实现了清洁工具接口,所以必须实现清洁方法
*@version1.0
*@authorChen.yu
*上海Softworks对日软件人才培训中心版权所有
*/
publicclass Broom implements IClearEquipment {
/**
*扫帚的清洁方法
*/
publicvoid clear() {
System.out.println("The Cleaner Use Broom");
}
}

以下是DustCollector类的代码片断:

package cn.softworks.demo;
/**
*该类是用来描述吸尘器这个清洁工具的<br>
*它实现了清洁工具接口,所以必须实现清洁方法
*@version1.0
*@authorChen.yu
*上海Softworks对日软件人才培训中心版权所有
*/
publicclass DustCollector implements IClearEquipment {
/**
*扫帚的清洁方法
*/
publicvoid clear() {
System.out.println("The Cleaner Use Dust Collector");
}
}

以下是Cleaner类的代码片断:

package cn.softworks.demo;
/**
*该类是用来描述一个清洁工人的<br>
*清洁工人会使用清洁设备来进行清洁工作的
*
*@version1.0
*
*@authorChen.yu
*
*上海Softworks对日软件人才培训中心版权所有
*/
publicclass Cleaner {
/**
*这个方法的作用是定义清洁工人的清洁行为<br>
*可以肯定的是,清洁工人必须借助清洁设备才能清洁
*
*@parameq使用的清洁设备
*/
publicvoid clear(IClearEquipment eq) {
//清洁工人使用清洁设备进行清洁
eq.clear();
}
}

softworks.cfg.properties配置文件:
ClearEquipment=cn.softworks.demo.DustCollector

代码工作原理:
通过以上代码可以知道,现在有一个清洁工类(Cleaner),两个清洁设备类(DustCollector和Broom他们都实现了清洁设备接口(IClearEquipment)),Cleaner工人的清洁方法(Clear)明确要求指明,清洁工人究竟使用哪个清洁设备来工作,为了增加系统的灵活性,我们把清洁工人所需要使用的清洁设备在“softworks.cfg.properties”配置文件做出了定义,并且利用BeanFactory从配置文件中读出了清洁设备的名字,并利用反射机制将该清洁设备传入到了Cleaner类的clear方法中。这样一来系统的灵活读就上升了,我们如果系统需要更改清洁设备,那么我们只需要更改配置文件中的类名就可以了,整个系统的代码都不需要变更,因此反射机制不但解决了系统耦合,而且还大大增加了系统的灵活性。
但是读者可能要问这样,以上代码确实可以解决BroomCleaner类之间耦合问题,也可以增加系统的灵活性,那么CleanerBeanFactory之间的耦合性问题又显现出来了,这个问题又如何解决呢?
以上这个问题我们可以利用Spring框架中的IoC(依赖注射来解决),具体的实现和解决方法,详情可以浏览:
上海Softworks软件人才培训中心
电话:021-53086530 53086531
地址:上海市北京东路668号科技京城东楼9楼E座
网址:www.softworks.cn
分享到:
评论

相关推荐

    论文研究-基于农业生态系统耦合的退耕还林工程影响评估.pdf

    论文研究-基于农业生态系统耦合的退耕还林工程影响评估.pdf, 基于黄土丘陵退耕区米脂、安塞和吴起三县的农户抽样调查数据, 运用灰色关联分析法定量测算该区域农业生态...

    双声子两能级系统耦合的解析解

    双声子两能级系统耦合的解析解,韩榕生,吴国庆,耗散两能级系统中存在复杂的非线性关系,导致无法进行完全求解。本文采用了相干近似的方法分析了两能级系统与双声子耦合的模型。

    FBG耦合模理论反射谱仿真.zip

    光纤布拉格光栅仿真反射谱、不同光栅长度对应的光纤布拉格光栅仿真反射谱、不同折射率调制深度对应的光纤布拉格光栅仿真反射谱、不同耦合系数情况下峰值反射率与光栅长度的关系曲线、不同光栅长度情况下峰值反射率与...

    工后立体交叉隧道系统动力学耦合作用机制

    工后立体交叉隧道系统动力学耦合作用机制,刘镇,周翠英,立体交叉隧道系统力学耦合作用机制是立体交叉隧道稳定性研究的重点与难点之一。基于工后立体交叉隧道系统耦合作用影响因素分析,

    RFID技术中的RFID系统按照耦合类型进行分类

    (1)电感耦合系统 ... 在电磁反向散射耦合系统中9读写器和电子标签之间的射频信号的实现为雷达原理模型,发射出去的电磁波,碰到目标后被反射,同时携带回目标信息。该系统依据的是电磁波的空间传输规律,如图

    采动诱发隐伏陷落柱突水机制与渗流耦合模型研究

    以桃园煤矿1035工作面突水事故为研究对象,分析了采动煤岩体破坏诱发隐伏陷落柱的突水原因与机制。并针对突水地点的地质条件,基于Darcy、Brinkman、Navier-Stokes(NS)方程,建立了简化的三维隐伏陷落柱突水非线性渗流...

    高科技企业创新生态系统耦合路径及激励机制研究

    高科技企业创新生态系统耦合路径及激励机制研究,张利飞,彭莹莹,创新生态系统是由高科技企业以技术标准为创新耦合纽带,在全球范围内形成的基于构件/模块的知识异化、协同配套、共存共生、共同�

    光纤-反射器耦合的后向反射功率耦合系数

    并且,给出光纤与几种典型反射器耦合的后向反射功率耦合系数的表示式以及当反射器沿光纤-反射器系统的轴向移动时耦合系数的曲线分布.还对光纤-平面镜和光纤-“猫眼”反射器的后向反射功率耦合系数的曲线分布作了实验...

    C#反射机制

    C#里面详解反射机制, Assembly类可以获得程序集的信息,也可以动态的加载程序集,以及在程序集中查找类型信息,并创建该类型的实例。 使用Assembly类可以降低程序集之间的耦合,有利于软件结构的合理化。

    耦合、耦合器件详解之我见

    耦合指信号由第一级向第二级传递的过程,一般不加注明时往往是指交流耦合。退耦是指 对电源采取进一步的滤波措施,去除两级间信号通过电源互相干扰的影响。...耦合电容值与第二级输入阻抗值乘积对应的时间常数。

    船舶工业产业集群耦合机制与耦合度测度模型研究

    船舶工业产业集群耦合机制与耦合度测度模型研究,苏屹,安晓丽,回顾船舶工业产业集群耦合的相关研究,并对船舶工业产业发展现状进行分析。在船舶工业产业集群耦合内涵界定与耦合特征分析的基础

    森林碳平衡对CO2浓度升高的响应与碳氮耦合机制

    森林碳平衡对CO2浓度升高的响应与碳氮耦合机制,江军,谢锦升,大气CO2浓度不断升高,对整个陆地生态系统产生了一系列的影响,而森林作为陆地生态系统的重要碳库,其对大气CO2浓度升高的响应主要

    磁耦合谐振式无线电能传输系统建模与分析

    磁耦合谐振式无线电能传输技术具有传输距离中等、传输效率高、能穿过非磁导性障碍物传输电能 等优点,使其有望取代电池为...离下系统的传输效率与负载功率进行了分析,得出了不同耦合状态下系统获得最大负载功率的条件

    区域煤炭产业经济-资源-环境系统耦合协调发展分析

    以山西省为例,建立煤炭产业经济-资源-环境(ERE)系统耦合协调度评价指标体系,计算煤炭产业经济、资源和环境各子系统综合发展水平,构建耦合协调度发展模型,对经济-资源-环境系统耦合协调发展水平进行多维测度与分析。...

    科技创新与科技金融耦合系统模型多维测度

    在建立科技金融与科技创新耦合协调系统评价指标体系的基础上,采用属性层次模型和熵值法确定指标权重,运用耦合系统模型从时空维度对湖南省科技金融与创新的协调发展程度进行应用研究。从时间维度研究表明:2001-2012年...

    光纤耦合器的耦合比与耦合区长度关系的仿真

    光电子课程设计的优秀文档,关于光纤耦合器的耦合比与耦合区长度关系的仿真。

    耦合系数求解.zip_matlab 交叉耦合_matlab 耦合系数_matlab计算耦合_交叉耦合_耦合系数

    利用MATLAB程序来计算交叉耦合系数,

    浮式平台与锚泊系统耦合技术研究

    浮式平台与锚泊系统耦合技术研究,秦洪德,付爽,锚泊系统定位技术属于深水浮式结构设计关键技术,随着作业水深的不断加深,浮体对锚泊系统的动力响应影响已不容忽视。采用耦合分

    电-气-热综合能源系统耦合优化调度 关键词:综合能源系统 优化调度 电气热耦合 仿真平台:MATLAB+CPLEX 主要内容

    主要内容:代码主要做的是一个考虑电网、热网以及气网耦合调度的综合能源系统优化调度模型,考虑了电网与气网,电网与热网的耦合,算例系统中,电网部分为10机39节点的综合能源系统,气网部分为比利时20节点的配气...

Global site tag (gtag.js) - Google Analytics