zhengshuo 发表于 2013-2-3 14:13:51

spring IOC 简易实现

java的反射机制在java基础中是非常重要的,曾经有人说过:反射是评判一个java程序员的标准。足见反射机制在java的重要性!

    当今javaee编程,所有的框架都封装了许多我们看不到的代码,所有都做成了可配置的模式,这让许多程序员只懂得如何使用这些框架而忽略了很多实质性的东西,今日我的第一篇博文就主要是来谈论一些简单的反射与xml结合的强大功能。
   
    在web项目中,我们熟悉的ssh框架都有xml配置文件,拿spring来说,它配置一个bean实际上也用到了反射和xml,我花了一个下午的时间来做了一个实现配置bean的例子,供来客参考:
下面是反射实现的一个实例化对象的工具类
package refenceTest;import java.lang.reflect.Method;import java.util.Map;import java.util.Set;public class RefenceUtils {/** * @author 石叶 * @param RefenceUtils * @param className 表示要创建类的类名(带包名) * @param parameters 表示要创建类的属性和属性对应值的一个MAP 属性名为key,值为value组成 * @return 返回对应的class的实例 * @throws Exception */public static Object getInstance(String className,Map<String,Object> parameters) throws Exception{/* * 通过类名获得类的实例 */Object obj = Class.forName(className).newInstance();/* 通过传入的map 拿到所有要赋值的属性*/Set<String> set = parameters.keySet();for(String str :set){/* 通过属性名的到对应的set方法名,这里必须保证set方法符合规范*/String methodName = "set"+str.substring(0, 1).toUpperCase()+str.substring(1);/*拿到set方法名对应的method*/Method m = obj.getClass().getMethod(methodName, obj.getClass().getDeclaredField(str).getType());/*执行这个set方法*/m.invoke(obj, parameters.get(str));}return obj;}}
这个就是解析xml的类,将解析出来的参数通过反射实例化后保存到beanMap中package xmlUtils;import java.io.File;import java.net.MalformedURLException;import java.util.HashMap;import java.util.Iterator;import java.util.Map;import org.dom4j.Attribute;import org.dom4j.Document;import org.dom4j.DocumentException;import org.dom4j.Element;import org.dom4j.io.SAXReader;import refenceTest.RefenceUtils;/** * 用于解析xml的类,将解析的对象通过反射实例化后存放在beanMap中 * @author 石叶 * */public class XmlLoad {/*用于存放实例对象的map*/private Map<String,Object> beanMap = new HashMap<String,Object>();/*xml文件*/private File resource;/*用dom4j中的SAXReader进行解析*/private SAXReader reader;/*解析中用到的document对象*/private Document document;public XmlLoad(){}/*通过构造实例化实例变量并完成解析*/public XmlLoad(File resource){this.resource = resource;try {reader = new SAXReader();document = reader.read(resource);this.loadObjectFromXml();} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}/*用于解析xml文件,实例化定义在xml中的变量,并存放在beanMap中*/private void loadObjectFromXml() throws Exception{Element root = document.getRootElement();Iterator rootIt = root.elementIterator();while(rootIt.hasNext()){Element classElement = (Element)rootIt.next();if("class".equals(classElement.getName())){Iterator classIt = classElement.attributeIterator();Map<String,Object> map = new HashMap<String,Object>();String refname = "";String className = "";String packageName = "";while(classIt.hasNext()){Attribute attri = (Attribute)classIt.next();if("type".equalsIgnoreCase(attri.getName())){className =attri.getValue();}if("package".equalsIgnoreCase(attri.getName())){packageName = attri.getValue();}if("name".equalsIgnoreCase(attri.getName())){refname = attri.getValue();}}if(!"".equals(packageName.trim())&&!"".equals(className.trim())){className =packageName+"."+className;}Element e = null;classIt = classElement.elementIterator();while(classIt.hasNext()){Element el = (Element)classIt.next();if("parameters".equals(el.getName())){e = el;}}Iterator it = e.elementIterator();while(it.hasNext()){Element element = (Element)it.next();Iterator attIt = element.attributeIterator();String name = "";String value = "";String ref = "";Object obj = null;while(attIt.hasNext()){Attribute attri = (Attribute)attIt.next();if("name".equals(attri.getName().trim())){name = attri.getValue();}if("value".equals(attri.getName().trim())){value = attri.getValue();}if("ref".equals(attri.getName().trim())){ref = attri.getValue();obj = beanMap.get(ref);}}if(null==obj){map.put(name, value);}else{map.put(name, obj);}}beanMap.put(refname,RefenceUtils.getInstance(className, map));}}}/*用于获得beanMap中的实例对象的入口*/public Object getBean(String key){return beanMap.get(key);}public File getResource() {return resource;}public void setResource(File resource) {this.resource = resource;}public Document getDocument() {return document;}public void setDocument(Document document) {this.document = document;}public SAXReader getReader() {return reader;}public void setReader(SAXReader reader) {this.reader = reader;}}
下面是供测试用的pojo
package pojo;/** ** @author 石叶 * */public class Person {/** * 姓名 */private String name;/** * 年龄 */private String age;/** * 性别 */private String sex;public String getAge() {return age;}public void setAge(String age) {this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}@Overridepublic String toString() {return this.getClass().getName()+":"+this.getName()+":"+this.getAge()+":"+this.getSex();}public Person(String name, String age, String sex) {super();this.name = name;this.age = age;this.sex = sex;}public Person() {super();}}package pojo;/** * 账户类 * @author 石叶 * */public class Account {/** * 账户id */private String id;/** * 账户姓名 */private String username;/** * 账户余额 */private String salary;/** * 在此person并无实际意义,只是为了测试配置中的ref属性 */private Person person;public Account() {super();}public String getId() {return id;}public void setId(String id) {this.id = id;}public Person getPerson() {return person;}public Account(String id, String username, String salary, Person person) {super();this.id = id;this.username = username;this.salary = salary;this.person = person;}public void setPerson(Person person) {this.person = person;}public String getSalary() {return salary;}public void setSalary(String salary) {this.salary = salary;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}@Overridepublic String toString() {return this.getClass().getName()+":"+this.getPerson().toString()+":"+this.getUsername()+":"+this.getSalary();}}package pojo;/** * 桌子 * @author 石叶 * */public class Desk {/** *宽*/private String widths;/** * 高 */private String heigths;/** * 长 */private String lengths;public String getHeigths() {return heigths;}public void setHeigths(String heigths) {this.heigths = heigths;}public String getLengths() {return lengths;}public void setLengths(String lengths) {this.lengths = lengths;}public String getWidths() {return widths;}@Overridepublic String toString() {return this.getClass().getName()+":"+this.getLengths()+":"+this.getWidths()+":"+this.getHeigths();}public void setWidths(String widths) {this.widths = widths;}public Desk() {super();}public Desk(String widths, String heigths, String lengths) {super();this.widths = widths;this.heigths = heigths;this.lengths = lengths;}}
下面是配置的xml文件
<?xml version="1.0" encoding="UTF-8"?><classes><class name="person" type="pojo.Person"><parameters><parameter name="name" value="zhengshuo"/><parameter name="age" value="21"/><parameter name="sex" value="��"/></parameters></class><class name="desk" type="pojo.Desk"><parameters><parameter name="widths" value="100"/><parameter name="heigths" value="120"/><parameter name="lengths" value="100"/></parameters></class><class name="account" type="pojo.Account"><parameters><parameter name="username" value="֣˶"/><parameter name="id" value="17"/><parameter name="salary" value="1000"/><parameter name="person" ref="person"/></parameters></class></classes>
测试类
package test;import java.io.File;import refenceTest.RefenceUtils;import xmlUtils.XmlLoad;public class Test {public static void main(String[] args) throws Exception {//这里需要改为大家存放这个xml的路径XmlLoad load = new XmlLoad(new File("d:/cvsroot/testrefence/src/pojo.xml"));Object obj = load.getBean("person");System.out.println(obj);obj = load.getBean("desk");System.out.println(obj);obj = load.getBean("account");System.out.println(obj);}}
这个代码虽短,但是可以很好的理解spring的配置bean,这里要强调的是spring返回的是一个代理,然后实现aop,在这里我没有aop的实现,当然日后有时间我在修改的更加完善,欢迎大家提出宝贵的意见!
页: [1]
查看完整版本: spring IOC 简易实现