Spring是众多开源 Java 项目中的一员,基于分层的 JavaEE 应用一站式轻量级开源框架,主要核心是IOC控制反转(Inversion of Control, IoC)和依赖注入(Dependency Injection, DI)这两大技术。
下面是一个非常原始,简易的BeanFactory。
通过创建Factory对象调用到构造器,构造器再调用方法,实现自动解析XML配置文件,实例化对象,并完成依赖注入。

1 /** 2 * IOC工厂接口的实现类 3 * 1.在创建实现类对象时解析XML文件 4 * 2.分析解析后的内容,通过反射创建对象,装入HashMap中 5 * 3.根据传入的className返回指定对象 6 * 4.依赖注入,给属性赋值(对象) 7 */ 8 public class Factory02 implements Factory { 9 //用于存放解析xml后得到的bean对象 10 private List<FactoryBeans> beans = new ArrayList<>(); 11 //用于存放完成实例化后的对象 12 private Map<String,Object> map = new HashMap<>(); 13 14 public Factory02(String fileName){ 15 this.parseXml(fileName); 16 this.instanceBean(); 17 this.setBeanProperty(); 18 } 19 20 /** 21 * 为实例化的对象赋值 22 */ 23 private void setBeanProperty() { 24 if(beans.size()>0){ 25 for(FactoryBeans factoryBeans : beans){ 26 //获取当前bean对象中的property对象集合 27 List<PropertyBean> subElementList = factoryBeans.getPropertyBeanList(); 28 if(subElementList!=null && subElementList.size()>0){ 29 for(PropertyBean propertyBean : subElementList){ 30 //获取当前property对象中的id 31 String id = propertyBean.getId(); 32 //首字母大写 用于拼接set方法 33 id = id.toUpperCase().charAt(0)+id.substring(1); 34 //获取当前property对象中的ref 35 String ref = propertyBean.getRef(); 36 //获取当前bean对象的类对象 37 Class clazz = map.get(factoryBeans.getId()).getClass(); 38 try { 39 //1.拼接set方法 2.传入set方法所需要的形参(通过property对象中的ref引用 查找到map中已经生成的对象 40 // 获取它的Class类对象) 41 Method method = clazz.getDeclaredMethod("set"+id,map.get(ref).getClass()); 42 //执行该set方法 1.指定调用该set方法的类 2.赋的值 即map中已经创建出的指定对象 43 method.invoke(map.get(factoryBeans.getId()),map.get(ref)); 44 } catch (Exception e) { 45 e.printStackTrace(); 46 } 47 } 48 } 49 } 50 } 51 } 52 53 /** 54 * 实例化解析的得到的数据 55 */ 56 private void instanceBean(){ 57 if(beans.size()>0){ 58 try { 59 for(FactoryBeans factoryBeans : beans){ 60 //key为id,value为通过全限定名class实例化得到的对象 61 map.put(factoryBeans.getId(),Class.forName(factoryBeans.getClazz()).newInstance()); 62 } 63 } catch (InstantiationException e) { 64 e.printStackTrace(); 65 } catch (IllegalAccessException e) { 66 e.printStackTrace(); 67 } catch (ClassNotFoundException e) { 68 e.printStackTrace(); 69 } 70 } 71 } 72 73 /** 74 * 解析XML 75 * @param fileName XML文件名 76 */ 77 private void parseXml(String fileName){ 78 //获取XML的唯一指定资源标识符 79 URL url = this.getClass().getClassLoader().getResource(fileName); 80 if(url!=null){ 81 //创建sax解析对象 82 SAXReader saxReader = new SAXReader(); 83 try { 84 //解析该url指向的文件 85 Document document = saxReader.read(url); 86 //配置xPath需要解析的内容 即所有beans标签后的bean标签中的内容 87 XPath xPath = document.createXPath("beans/bean"); 88 //指定解析标签的范围为当前整个XML文件(document) 89 List<Element> elementList = xPath.selectNodes(document); 90 if(elementList!=null || elementList.size()>0){ 91 for(Element element : elementList){ 92 //解析property标签中的内容 93 xPath = document.createXPath("property"); 94 //指定范围为当前元素下(element) 95 List<Element> subElementList = xPath.selectNodes(element); 96 //创建属性类对象的集合备用 97 List<PropertyBean> propertyBeanList = null; 98 //通过解析bean标签得到的id和全限定名 创建factoryBeans对象 99 FactoryBeans factoryBeans = new FactoryBeans(element.attributeValue("id"),element.attributeValue("class")); 100 //判断当前元素中是否包含属性property标签 101 if(subElementList!=null && subElementList.size()>0){ 102 propertyBeanList = new ArrayList<>(); 103 //遍历该bean标签中所有的property标签 创建相对应的property对象 104 for(Element subElement : subElementList){ 105 //装入集合中 106 //PropertyBean对象中有两个元素 107 //id:用于创建用来赋值的set方法 除了首字母 其它字符须和被赋值的属性保持一致 108 //ref:用于引用其它bean标签 ref必须和被引用的bean标签id保持一致 109 propertyBeanList.add(new PropertyBean(subElement.attributeValue("id"),subElement 110 .attributeValue("ref"))); 111 } 112 //将property标签创建的对象装入factoryBeans的集合属性中 113 //每个factoryBeans都带有一个集合属性 专门用于存放property对象 114 //如果XML中该bean标签下没有property标签 则不会有任何集合产生 115 //反之有多少个property标签 就会有多少个property对象生成并装入该集合中 116 factoryBeans.setPropertyBeanList(propertyBeanList); 117 } 118 //将factoryBeans对象装入集合中 119 beans.add(factoryBeans); 120 } 121 }else{ 122 System.out.println("未解析元素"); 123 } 124 } catch (Exception e) { 125 e.printStackTrace(); 126 } 127 128 }else{ 129 System.out.println("未找到文件"); 130 } 131 } 132 133 /** 134 * IOC工厂接口的实现类方法 135 * @param className 类名 136 * @return 指定类的对象 137 */ 138 @Override 139 public Object getObject(String className) { 140 return map.get(className); 141 } 142 }
初见Spring,如有错误的地方,希望对这方面有研究的朋友指出,谢谢!