JAVA反射机制的简单应用(1)
Spring中的IOC(控制翻转,又叫依赖注入)
先来看一个例子,A对象关联B对象,学过UML的都知道这是指A类中有一个B类的成员变量,那么我们在创建A对象时,可以用构造函数或者set方法将B类对象与A类对象关联在一起,这种A与B之间的关系需要我们在代码中表现出来,我们也可以把这些代码叫做 硬编码 。
那么依赖注入所要解决的问题便是将这两个对象之间的关联关系的设置过程交给一个配置文件去维护,配置文件中指明了我们要将哪个B对象注入到A对象当中,这里涉及到工厂模式,需要有一个工厂对象,这个对象读取配置文件,根据配置文件的设置来完成B对象的创建以及属性注入的功能,这样当改变两个对象间的关系时,只需要改变配置文件即可,这样就摆脱了依赖注入的局限。
下面实现一个简单的反射应用,从xml文件中读取配置信息,利用反射创建 Employee,Address 实例并将Address实例与Employee实例关联在一起,这一切全是由BeanFactory类完成的,我们不会在类中写上 以下硬编码 ,
Employee e = new Employee();
Address addr = new Address();
...
e.setAddr(addr);
而是由BeanFactory类根据配置文件bean.xml中的配置信息自动实现和上述代码同样的功能,很多框架底层也是这样来实现的。
<?xml version="1.0" ?> <beans> <bean id="b01" class="edu.zhutong.reflection.application.Employee"> <property name="name" value="zhutong"></property> <property name="age" value="24"></property> <property name="salary" value="7000.53"></property> <property name="addr" ref="b03"></property> </bean> <bean id="b02" class="edu.zhutong.reflection.application.Address"> <property name="street" value="PingLeYuan"></property> <property name="no" value="No100"></property> </bean> <bean id="b03" class="edu.zhutong.reflection.application.Address"> <property name="street" value="SongYuDongLi"></property> <property name="no" value="No23"></property> </bean> </beans>
public class Employee { private String name; private int age; private double salary; private Address addr; public Employee() { super(); } public Address getAddr() { return addr; } public void setAddr(Address addr) { this.addr = addr; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; } public String toString(){ return "Employee name="+name+" age="+age+" salary="+salary+" address="+addr; } }
public class Address { private String street; private String no; public Address() { super(); } public String getNo() { return no; } public void setNo(String no) { this.no = no; } public String getStreet() { return street; } public void setStreet(String street) { this.street = street; } public String toString(){ return street+" No"+no; } }
public class BeanFactory { private Map<String,Element> map=new HashMap<String,Element>(); //在构造方法中载入xml文件,将Element对象以id为key放入Map public BeanFactory(){ try { DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance(); DocumentBuilder db=dbf.newDocumentBuilder(); Document doc=db.parse("beans.xml"); NodeList nl=doc.getElementsByTagName("bean"); for(int i=0;i<nl.getLength();i++){ Element e=(Element)nl.item(i); String id=e.getAttribute("id"); map.put(id, e); } } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } public Object getBean(String id){ try { //分析class属性 利用反射创建对象 Element ele=map.get(id); String className=ele.getAttribute("class"); Class c=Class.forName(className); Object result=c.newInstance(); //逐个为result对象设置属性 NodeList children=ele.getElementsByTagName("property"); for(int i=0;i<children.getLength();i++){ Element child=(Element)children.item(i); //获得属性名 String fieldName=child.getAttribute("name"); String value=child.getAttribute("value"); String ref=child.getAttribute("ref"); //获得属性类型 Field f=c.getDeclaredField(fieldName); Class type=f.getType(); //获得设置属性的方法名 char[] cs=fieldName.toCharArray(); cs[0]-=32; String methodName=new String(cs); methodName="set"+methodName; //利用反射,调用setXXX方法,设置属性值 Method m=c.getDeclaredMethod(methodName, type); Object o=value; if (value.equals("")){ o=getBean(ref); } else{ String valueClassName=type.getSimpleName(); if (valueClassName.equals("int")) o=new Integer(value); if (valueClassName.equals("double")) o=new Double(value); } m.invoke(result, o); } return result; } catch (Exception e) { e.printStackTrace(); return null; } } }
name= zhutong age= 24 height= 7000.53 street= SongYuDongLi no=No23