文章目录
- 概要
- 根据需求编写XML文件,配置需要创建的bean
- 编写程序读取XML文件,获取bean相关信息,类,属性,id
- 前提知识点Dom4j
- 根据第二步获取到的信息,结合反射机制动态创建对象,同时完成属性赋值
- 将创建好的bean存入到Map集合,设置key-value映射
- 提供方法从Map中通过id获取到对象的value
概要
文章是看楠哥的视频做的总结,加上自己一些补充,为了方便以后的复习
视频地址
Spring ioc核心技术:
xml解析和反射
根据需求编写XML文件,配置需要创建的bean
实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Car {
private Integer num;
private String brand;
}
xml文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
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="car1" class="network.hylnetwork.entity.Car">
<property name="num" value="1"></property>
<property name="brand" value="奥迪"></property>
</bean>
<bean id="car2" class="network.hylnetwork.entity.Car">
<property name="num" value="2"></property>
<property name="brand" value="奥拓"></property>
</bean>
</beans>
编写程序读取XML文件,获取bean相关信息,类,属性,id
前提知识点Dom4j
DOM4J简介
DOM4J是 dom4j.org 出品的一个开源 XML 解析包。DOM4J应用于 Java 平台,采用了 Java 集合框架并完全支持 DOM,SAX 和 JAXP。
DOM4J 使用起来非常简单。只要你了解基本的 XML-DOM 模型,就能使用。
Dom:把整个文档作为一个对象。
DOM4J 最大的特色是使用大量的接口。
了解更多参考:Dom4j完整教程详解
导入dom4j依赖
<!-- dom4j-->
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
仿写ClassPathXmlApplicationContext实现ApplicationContext
public class MyClassPathXmlApplicationContext implements ApplicationContext{
}
实现ApplicationContext的方法
测试能否获取xml文件,在MyClassPathXmlApplicationContext添加无参构造和parseXMl方法
public MyClassPathXmlApplicationContext(String path){
parseXML(path);
}
public void parseXML(String path){
SAXReader saxReader = new SAXReader();
try {
Document document = saxReader.read("src/main/resources/"+path);//看提示
System.out.println(document);
} catch (DocumentException e) {
e.printStackTrace();
}
}
测试类
public class Test {
public static void main(String[] args) {
ApplicationContext applicationContext = new MyClassPathXmlApplicationContext("spring-ioc.xml");
}
}
成功获取xml文件,也就是我们获取到了spring-ioc.xml文件,如下运行结果提示因为路径不完整,需要手动拼接不完整部分项目路径,否则就会出现如下错误)
可以看到缺少了“src/main/resources/”部分,所以我们手动拼接上
org.dom4j.DocumentException: G:\AllSpace\IdeaSpace\Spring\spring-ioc.xml (系统找不到指定的文件。) Nested exception: G:\AllSpace\IdeaSpace\Spring\spring-ioc.xml (系统找不到指定的文件。
获取根节点,也就是我们xml文件中的beans
public void parseXML(String path){
SAXReader saxReader = new SAXReader();
try {
Document document = saxReader.read("src/main/resources/"+path);//看提示
Element rootElement = document.getRootElement();
System.out.println(rootElement);
} catch (DocumentException e) {
e.printStackTrace();
}
}
运行结果如下
xml解析就像剥洋葱一样,是一层一层往下走的
获取根节点的迭代器,其实也就是为了得到beans中的bean
public void parseXML(String path){
SAXReader saxReader = new SAXReader();
try {
Document document = saxReader.read("src/main/resources/"+path);//看提示
Element rootElement = document.getRootElement();
Iterator<Element> rootIter = rootElement.elementIterator();//根节点迭代器
while (rootIter.hasNext()){
Element bean = rootIter.next();//获取bean
System.out.println(bean);
}
} catch (DocumentException e) {
e.printStackTrace();
}
}
运行结果如下
将beans中的两个bean都获取到了
获取到bean之后就是获取bean的类、属性、id信息
public void parseXML(String path){
SAXReader saxReader = new SAXReader();
try {
Document document = saxReader.read("src/main/resources/"+path);//看提示
Element rootElement = document.getRootElement();
Iterator<Element> rootIter = rootElement.elementIterator();//根节点迭代器
while (rootIter.hasNext()){
Element bean = rootIter.next();//获取bean
String idstr = bean.attributeValue("id"); //获取bean中的id
String className = bean.attributeValue("class"); //获取bean中的class
System.out.println(idstr);
System.out.println(className);
}
} catch (DocumentException e) {
e.printStackTrace();
}
}
结果如下
可以看到和xml配置文件中的信息相匹配
获取属性 也就是bean中的property
给属性赋值
Iterator<Element> beanIter = bean.elementIterator();
while (beanIter.hasNext()){
Element property = beanIter.next();
System.out.println(property);
}
结果如下
对应了四个property
根据第二步获取到的信息,结合反射机制动态创建对象,同时完成属性赋值
// 反射动态创建对象
Class clazz = Class.forName(className);
Constructor constructor = clazz.getConstructor();
将创建好的bean存入到Map集合,设置key-value映射
private Map<String,Object> iocMap; //创建map集合
public MyClassPathXmlApplicationContext(String path){
iocMap = new HashMap<>();
parseXML(path);
}
public void parseXML(String path){
SAXReader saxReader = new SAXReader();
try {
Document document = saxReader.read("src/main/resources/"+path);//看提示
Element rootElement = document.getRootElement();
Iterator<Element> rootIter = rootElement.elementIterator();//根节点迭代器
while (rootIter.hasNext()){
Element bean = rootIter.next();//获取bean
String idstr = bean.attributeValue("id"); //获取bean中的id
String className = bean.attributeValue("class"); //获取bean中的class
// 反射动态创建对象
Class clazz = Class.forName(className);
Constructor constructor = clazz.getConstructor();
Object object = constructor.newInstance();
iocMap.put(idstr,object); //将bean存入map集合中,设置key-value映射
}
} catch (DocumentException | ClassNotFoundException | NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
提供方法从Map中通过id获取到对象的value
修改getBean方法
@Override
public Object getBean(String s) throws BeansException {
return iocMap.get(s);
}
测试类
public class Test {
public static void main(String[] args) {
ApplicationContext applicationContext = new MyClassPathXmlApplicationContext("spring-ioc.xml");
Object car1 = applicationContext.getBean("car1");
System.out.println(car1);
}
}
运行结果如下