前边一篇博客写过相关反射机制的基础知识:java中的反射机制。写完这篇后有一条评论“反射反射程序员的快乐”,为什么说“快乐呢”,咱们看看反射的强大功能吧!这篇博客简单说一下反射机制的运用。
反射机制,很多来说是Java中比较那学的东西,为什么?很多说是因为它比较抽象!说的也对,因为理解不了么,所以比较抽象。但是经过项目实践,框架的深究,感觉到反射有着强大的作用。是很多优秀框架的技术根源,是实现复用,达到解耦合的有利得手。因为反射不需要直到类,xml文件,等等的内容,只需要我们提前制定一种规则,那么我们就可以通过反射使我们的系统达到异常灵活的地步,使我们的开发有了那些提前写好可复用的代码——框架,这些可都是基于反射的强大作用。
从现实生活中,我们找个反射的例子吧?什么类似Java中的反射机制呢???画家,它会画人像。来人出钱画个上学的学生,他马上画出来了;有来人出钱画个收小麦的农民,他也画出来了…… 这就像我们的反射,过来什么类我们进行反射获取具体的类,就可以用它了,不用提前知道传过来的类的具体。而假如我们传统的new对象的画,必须知道传过来的对象,这样就很难达到多态的效果了。就像这个画家,如家就会画上学的儿童,那么那些想让他画农民的客户来了,就白跑了,这样显得画家的水平特别低了。转到我们的软件就是软件的功能特别单一了。
那么通过反射在那些地方用的到呢?这里举两个例子:
一,1,问题描述:一般在servlet或者anction类中,我们通过获取request中的数据,进行数据的封装,需要利用request的getParameter一一取出数据来,然后再通过对象的set方法进行赋值,这样来看是非常麻烦呢?
2,问题解决:通过反射我们可以不用知道request传过来的数据,只需要知道我们要封装的对象,就可以进行赋值,一次代码重复利用,达到了很好的复用效果。
我们来看这个工具类:
/**
* 工具类
* @author Administrator
*/
public class WebUtil {
/**
* 通过反射机制将request对象中保存的数据设置到某个java对象中。
* @param request 请求对象,该对象中保存了用户从表单中提交的数据
* @param o java对象
*/
public static void makeRequestToObject(HttpServletRequest request,Object o){
//获取类型
Class c = o.getClass();
//获取用户提交所有数据的name
Enumeration<String> names = request.getParameterNames();
//循环所有的name
while(names.hasMoreElements()){
//这里的name就是用户提交数据“=”左边的值
String name = names.nextElement();
//拼接方法名
String methodName = "set" + name.toUpperCase().charAt(0) + name.substring(1);
//获取方法
try {
Method setMethod = c.getMethod(methodName, String.class);
//执行set方法,进行赋值
setMethod.invoke(o, request.getParameter(name));
} catch (Exception e) {
}
}
}
}
3,注意事项:当然,这里需要我们满足javabean规范,而且jsp页面的字段和bean里边的要一样等,就有一些规范了。
二,1,问题描述:一般三层架构和MVC架构的层与层之间实现解耦合,而直接的分层加接口,耦合度还是很高的,如何使之间彼此不受影响呢?
2,问题解决:利用反射:
public static void createService(){
// 创建所有的Service对象
// 利用XPATH指定查询条件
xpath = "//bean[@type='service']";
// 获取所有的service类型的节点
List<Element> serviceNodeList = doc.selectNodes(xpath);
// 创建每一个service类型的对象,并存储到临时的内存空间中。
for (Element serviceElement : serviceNodeList) {
// 解析属性值
String id = serviceElement.attributeValue("id");
String className = serviceElement.attributeValue("class");
// 反射创建对象
Object serviceObject = Class.forName(className).newInstance();
// 得到业务对象的类
Class serviceClass = serviceObject.getClass();
// 保存到临时的map集合中
serviceObjectMap.put(id, serviceObject);
// 这里需用将此service和dao的对象进行组合,利用本身的set方法
List<Element> propertyElements = serviceElement.elements("property");
for (Element proElement : propertyElements) {
String fieldName = proElement.attributeValue("name");
String refId = proElement.attributeValue("refId");
// 获取关联对象
Object daoObject = daoObjectMap.get(refId);
// 获取对应的方法
String methodName = "set"+ fieldName.substring(0, 1).toUpperCase()+ fieldName.substring(1);
// 获取属性
Field fieldObj = serviceClass.getDeclaredField(fieldName);
Class fieldClazz = fieldObj.getType();
// 获取属性的set方法
Method methodOjbect = serviceClass.getDeclaredMethod(methodName,fieldClazz);
// 利用反射调用set方法,组合对象关系
methodOjbect.invoke(serviceObject, daoObject);
}
}
}
当然需要我们的xml文件来进行一些约束,有了一些规范:
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<!-- 声明Dao层的对象 -->
<bean id="userDao" type="dao" class="com.ljh.system.dao.impl.UserDaoImpl"></bean>
<!-- 声明Service对象 -->
<bean id="userService" type="service" class="com.ljh.system.service.impl.UserServiceImpl">
<property name="userDao" refId="userDao"></property>
</bean>
<!-- 声明Action对象 -->
<bean id="userAction" type="action" class="com.ljh.system.action.UserAction">
<property name="userService" refId="userService"></property>
</bean>
</beans>
这里是一个利用反射获取了service类,并且关联了dao类,感觉反射的作用是非常强大的。
通过项目的实践,不仅加深了对反射机制的理解,更感觉到了它的无限魅力,有了反射,感觉很多问题都迎刃而解了!