Spring Ioc底层实现
Posted Harmony_tqs
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Ioc底层实现相关的知识,希望对你有一定的参考价值。
原理和步骤
- Ioc容器的实现主要依赖的是xml解析和Java反射。
- 步骤:读取配置文件 -> 将其逐层“剥开”,获取各项属性 -> 通过各属性配合反射生成对象 -> 将其放入容器中,以供调用
具体实现
- 实体类 Book
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Book {
private Integer id;
private String name;
private Double price;
}
- 配置文件 spring.xml
<?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="threeBody" class="per.tan.ioc.Book">
<property name="id" value="1"/>
<property name="name" value="《三体》"/>
<property name="price" value="59.9"/>
</bean>
</beans>
- xml解析使用的是Dom4j,加入maven依赖
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.1</version>
</dependency>
- MyClassPathXmlApplicationContext。需要实现接口ApplicationContext,着重重写以下方法:
- 创建容器 Map
private final Map<String, Object> iocMap;
- 重写构造方法 此处将解析xml的步骤写在自定义方法parseXML
public MyClassPathXmlApplicationContext(String path) { iocMap = new HashMap<>(); parseXML(path); }
- parseXML()
//使用Dom4j进行xml解析 public void parseXML(String path) { SAXReader saxReader = new SAXReader(); try { //定义文档 Document document = saxReader.read("src/main/resources/" + path); //获取根节点,即<beans> Element beans = document.getRootElement(); //beans迭代器 Iterator<Element> beansIterator = beans.elementIterator(); while (beansIterator.hasNext()) { Element bean = beansIterator.next(); String idStr = bean.attributeValue("id"); String classStr = bean.attributeValue("class"); Class<?> clazz = Class.forName(classStr); Constructor<?> constructor = clazz.getConstructor(); //利用获取到的无参构造生成目标对象 Object object = constructor.newInstance(); //bean迭代器 Iterator<Element> beanIterator = bean.elementIterator(); while (beanIterator.hasNext()) { Element property = beanIterator.next(); //获取属性 String propertyName = property.attributeValue("name"); String propertyValue = property.attributeValue("value"); Field field = clazz.getDeclaredField(propertyName); //获取方法 String methodStr = "set" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1); Method method = clazz.getMethod(methodStr, field.getType()); Object value = propertyValue; //判断属性类型并转换 switch (field.getType().getName()) { case "java.lang.Integer": value = Integer.parseInt(propertyValue); break; case "java.lang.Double": value = Double.parseDouble(propertyValue); break; } method.invoke(object, value); } //装入容器 iocMap.put(idStr, object); } } catch (DocumentException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } }
- 重写getBean,根据名字从容器中获取bean
@Override public Object getBean(String s) throws BeansException { return iocMap.get(s); }
- 测试 Test
public class Test {
public static void main(String[] args) {
ApplicationContext context = new MyClassPathXmlApplicationContext("spring.xml");
Book book = (Book) context.getBean("threeBody");
System.out.println(book);
}
}
- 成果
D:\\Java_JDK\\JDK8\\bin\\java.exe ...
Book(id=1, name=《三体》, price=59.9)
Process finished with exit code 0
以上是关于Spring Ioc底层实现的主要内容,如果未能解决你的问题,请参考以下文章