针对上篇文章《JAVA反射原理》的图,再稍作补充:
这个图是上篇博客中图的一部分,实际上,这部分才是反射的核心,即:对象、class的相互关系:
如上篇文章所说,我们关注反射,是因为反射可以达到以下作用:
这些作用听起来没什么大不了,但是合理使用,威力很大:Struts、Hibernate、Spring、动态代理……没有反射,这些都白搭。
此处以Struts1为例,来看一下struts-config.xml:
<struts-config> <form-beans> <form-bean name="loginForm" type="com.tgb.struts.LoginActionForm"/> </form-beans> <action-mappings> <action path="/login" type="com.tgb.struts.LoginAction" name="loginForm" scope="request" > <forward name="success" path="/login_success.jsp" /> <forward name="error" path="/login_error.jsp"/> </action> </action-mappings> </struts-config>根据Struts1的运行机制,我们知道在ActionServlet截获请求后,会将页面数据存放到一个ActionForm中,然后把此ActionForm交由Action处理,使用如下:
LoginActionForm laf = (LoginActionForm)form;你可以发现ActionForm传给Action时,已经是一个对象了,这个对象从哪里来的?我们知道对象来源有两种:
Struts也仅仅知道你配置了一个loginForm,类是com.tgb.struts.LoginActionForm……,没错,Struts就是使用反射加载这些类,从而实例化ActionForm和Action的,大致过程如下:
Hibernate使用了ORM(Object/Relation Mapping)机制,R(Relation)来自数据库,O(Object)呢?来看一下hibernate映射文件:
<hibernate-mapping > <class name="com.tgb.hibernate.Person" table="t_person"> <id name="id"> <generator class="foreign" > <param name="property">idCard</param> </generator> </id> <property name="name" /> <one-to-one name="idCard" constrained="true" /> </class> </hibernate-mapping>看到<class name="com.tgb.hibernate.Person" table="t_person">,和上面说的Struts一样,也是使用到反射,以Hibernate的根据主键获取对象为例:session.get(Person.class, "0001"):
Class.forName("com.tgb.hibernate.Person")获取Person实例
调用Person的setter对属性赋值
返回此Person对象
Spring是一个大工厂,用于组织对象之间的关系,配置如下:
<bean id="userManager" class="com.tgb.usermgr.manager.UserManagerImpl"> <property name="logManager" ref="logManager"/> </bean> <bean id="logManager" class="com.tgb.usermgr.manager.LogManager" />简单说IoC的过程如下:
Class.forName("com.tgb.usermgr.manager.UserManagerImpl")实例化userManagerImpl
Class.forName("com.tgb.usermgr.manager.LogManager")实例化logManager
调用userManagerImpl的setLogManager,注入logManager
当使用userManagerImpl,已经是处理完依赖关系的userManagerImpl
可以说,只要在配置文件有对类名的标记,基本上就是为了利用到反射的特性。
package reflection; public class Person { public void eat() { System.out.println("im eating"); } }
package reflection; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class TestMethod { public static void main(String [] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException { //获取Person类 Class clazz=Class.forName("reflection.Person"); //实例化对象 Person p=(Person)clazz.newInstance(); //得到person的eat方法 Method m=clazz.getDeclaredMethod("eat",new Class[]{}); //执行person的eat方法 m.invoke(p, new Object[]{}); } }如上,知道一个类的某个方法名,再有这个类的实例,我们就可以执行这个函数。有对象,有函数名,我直接obj.method()不就行了?这就跟用不用MVC道理一样,不用照样可以完成功能,但是却少了灵活性。
关于反射细节,如在JVM中的执行流程,较为复杂,待以后整理清楚再说。
原文地址:http://blog.csdn.net/lidatgb/article/details/37573225