手写一个简单的IOC容器
手写一个简单的IOC容器 说明 首先我们都知道,Spring框架中两个最重要的组件就是IOC和AOP。IOC 即 inversion of control 控制反转。Aop即 Aspect Oriented Programming 面向切面编程。那么我们这里就来手写一个简单的IOC容器。这里主要使用 xml配置的方式来实现IOC容器。
前置知识 手撸一个IOC容器需要先掌握好 XML文件解析
和 Java反射
知识。
行了,下面我们就开始了。
项目搭建 创建项目 使用普通的maven搭建一个项目。
导入依赖 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 <dependencies > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-context</artifactId > <version > 5.2.3.RELEASE</version > </dependency > <dependency > <groupId > org.projectlombok</groupId > <artifactId > lombok</artifactId > <version > 1.18.10</version > </dependency > <dependency > <groupId > org.dom4j</groupId > <artifactId > dom4j</artifactId > <version > 2.1.1</version > </dependency > <dependency > <groupId > com.alibaba</groupId > <artifactId > fastjson</artifactId > <version > 1.2.62</version > </dependency > </dependencies >
实体类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 package com.ooyhao.pojo;import lombok.Data;import java.io.Serializable;@Data public class User implements Serializable { private byte age; private Byte ageB; private short height; private Short heightS; private int id; private Integer idI; private long weight; private Long weightL; private char sex; private Character sexC; private float salary; private Float salaryF; private double buy; private Double buyD; private boolean successB; private Boolean success; private String name; }
spring配置文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns ="http://www.springframework.org/schema/beans" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" > <bean id ="user" class ="com.ooyhao.pojo.User" > <property name ="age" value ="2" /> <property name ="ageB" value ="20" /> <property name ="height" value ="170" /> <property name ="heightS" value ="1700" /> <property name ="id" value ="1" /> <property name ="idI" value ="10" /> <property name ="weight" value ="60" /> <property name ="weightL" value ="600" /> <property name ="sex" value ="m" /> <property name ="sexC" value ="f" /> <property name ="salary" value ="7500.5" /> <property name ="salaryF" value ="9000.5" /> <property name ="buy" value ="10.05" /> <property name ="buyD" value ="100.5" /> <property name ="success" value ="false" /> <property name ="successB" value ="true" /> <property name ="name" value ="欧阳" /> </bean > </beans >
自定义ApplicationContext 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 public class MyApplicationContext implements ApplicationContext { private static Map<String,Object> beansContainer = new HashMap<>(); public MyApplicationContext (String path) { ClassPathResource resource = new ClassPathResource(path); SAXReader reader = new SAXReader(); try { Document document = reader.read(resource.getInputStream()); Element beansElement = document.getRootElement(); Iterator<Element> beansIter = beansElement.elementIterator(); while (beansIter.hasNext()){ Element beanElement = beansIter.next(); String id = beanElement.attributeValue("id" ); String className = beanElement.attributeValue("class" ); Class<?> aClass = Class.forName(className); Constructor<?> constructor = aClass.getConstructor(); Object o = constructor.newInstance(); Iterator<Element> beanIter = beanElement.elementIterator(); while (beanIter.hasNext()){ Element property = beanIter.next(); String fieldName = property.attributeValue("name" ); String fieldValue = property.attributeValue("value" ); Field field = aClass.getDeclaredField(fieldName); Class<?> fieldType = field.getType(); String setMethodName = "set" + fieldName.substring(0 ,1 ).toUpperCase()+ fieldName.substring(1 ); Method method = aClass.getMethod(setMethodName, fieldType); Object val = fieldValue; switch (fieldType.getName()){ case "int" : case "java.lang.Integer" : val = Integer.valueOf(fieldValue); break ; case "boolean" : case "java.lang.Boolean" : val = Boolean.valueOf(fieldValue); break ; case "char" : case "java.lang.Character" : val = fieldValue.charAt(0 ); break ; case "long" : case "java.lang.Long" : val = Long.valueOf(fieldValue); break ; case "double" : case "java.lang.Double" : val = Double.valueOf(fieldValue); break ; case "float" : case "java.lang.Float" : val = Float.valueOf(fieldValue); break ; case "byte" : case "java.lang.Byte" : val = Byte.valueOf(fieldValue); break ; case "short" : case "java.lang.Short" : val = Short.valueOf(fieldValue); break ; } method.invoke(o,val); } beansContainer.put(id,o); } } catch (DocumentException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } } public Object getBean (String s) throws BeansException { Object o = beansContainer.get(s); return o; } public <T> T getBean (Class<T> aClass) throws BeansException { Collection<Object> values = beansContainer.values(); Iterator<Object> iterator = values.iterator(); while (iterator.hasNext()){ Object next = iterator.next(); if (next.getClass().equals(aClass)) { return (T) next; } } return null ; } }
上述部分就是实现简单的IOC重点内容。主要是基于 XML解析和发射知识。
项目测试 项目测试代码
1 2 3 ApplicationContext context = new MyApplicationContext("spring.xml" ); User o = context.getBean(User.class ) ; System.out.println(JSONObject.toJSONString(o));
测试结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 { "age" : 2 , "ageB" : 20 , "buy" : 10.05 , "buyD" : 100.5 , "height" : 170 , "heightS" : 1700 , "id" : 1 , "idI" : 10 , "name" : "欧阳" , "salary" : 7500.5 , "salaryF" : 9000.5 , "sex" : "m" , "sexC" : "f" , "success" : false , "successB" : true , "weight" : 60 , "weightL" : 600 }
注意:这里只是实现了一个简单的IOC容器,并且只是实现了 java的简单类型和 包装类型,以及String类型的注入。