初见Spring

JAVA学习网 2018-09-26 16:30:03

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 BeanFactory

初见Spring,如有错误的地方,希望对这方面有研究的朋友指出,谢谢!

阅读(2145) 评论(0)