Manual development-simple Spring XML configuration-based program
Article directory
This article will lead you to write a simple Spring container. By reading the beans.xml configuration file, you can obtain the first JavaBean:Monster object, assign a value to the object, put it into the container, and output the object information.
Let's first review when using Spring, we ClassPathXmlApplicationContext
get the container, the container automatically reads the beans.xml configuration file, we get the object ioc
through the container method, and output the object.getBean
All you need to do now is:
- To implement an ioc container yourself, the premise is to implement one of your own
ClassPathXmlApplicationContext()
; ClassPathXmlApplicationContext()
Provide a getBean() method.
Thought analysis@
Here we actually focus on ClassPathXmlApplicationContext()
the specific implementation process:
- Define a
ioc
mappingConcurrentHashMap
that stores object name id and object. - Create a constructor and place all the following operations in this constructor
- Use
xml
parsing technologydom4j
tobeans.xml
read the information in the file and obtain the attribute values of the node information. - Create objects using reflection
- Place the object
ioc
into - provide a
getBean
method
When using xml parsing technology dom4j
to read the information in the beans.xml file and obtain the attribute values of the node information, you need to first obtain the path to the beans.xml file. The path here refers to the path where the compiled files of the project are located, that is, target
the path in the working directory. Our beans.xml file is placed resource
in the directory. After compilation, it will run to the target/classes directory, so here The directory we dom4j
read through should be D:/Java/JavaProjects/spring-context-v1/target/classes/
; the complete file working path should be D:/Java/JavaProjects/spring-context-v1/target/classes/beans.xml
;
String path = this.getClass().getResource("/").getPath();
// System.out.println("path="+path);
SAXReader saxReader = new SAXReader();
Document document = saxReader.read(new File(path + iocBeanXmlFile));
After getting document
the document object, we got all the contents in beans.xml. At this time, we got the root node, and then got the first bean object of the bean tag through the root node, the attributes in the bean tag and the Values can be obtained. You can get the full class path through the class attribute of the bean tag. Once you get the class path, you can create an object through reflection. The type of this object is the object of your class path.
SAXReader saxReader = new SAXReader();
Document document = saxReader.read(new File(path + iocBeanXmlFile));
Element rootElement = document.getRootElement();
Element bean = (Element) rootElement.elements("bean").get(0);
String id = bean.attributeValue("id");
String classFullPath = bean.attributeValue("class");
System.out.println("id="+id);
System.out.println("classFullPath="+classFullPath);
List<Element> property = bean.elements("property");
String monsterId = property.get(0).attributeValue("value");
String name = property.get(1).attributeValue("value");
System.out.println("monsterId="+monsterId);
System.out.println("name="+name);
Only objects created through reflection can have a similar structure to the Monster object. We can inject the attribute values of the bean object taken out from beans.xml into the object created by our reflection, and then add this object to the ioc collection.
Class<?> aClass = Class.forName(classFullPath);
Monster o = (Monster) aClass.newInstance();
o.setId(Integer.valueOf(monsterId));
o.setName(name);
ioc.put(id,o);
Finally, a getBean
method is provided to find the corresponding mapped Monster object from the ioc container when the monsterId is given.
public Object getBean(String id){
return ioc.get(id);
}
Finally, the above picture was realized. We only need to configure the bean object in the xml file, and then give the name of the xml file to the LingHuApplication
container for initialization to get an ioc container. The essence of the ioc container is one ConcurrentHashMap
. Internally, the configuration information of the bean object is read through dom4j, the object is created through reflection such as classFullPath, and the configuration information of the bean object is injected into the new object. This new object is put into it ConcurrentHashMap
, and we getBean(String monsterId)
traverse through methods ConcurrentHashMap
to find the new object.
The significance of doing these things is that we separate the configuration work and business work, and the tedious object management work is all completed through the configuration file, which reduces the coupling of the code and strips off the business code. So the essence of Spring's container idea is: ConcurrentHashMap
+Reflection creates objects.
Complete code &:
LingHuApplication.java:
package com.linghu.spring.linghuapplication;
import com.linghu.spring.bean.Monster;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.context.annotation.ComponentScan;
import java.io.File;
import java.net.MalformedURLException;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author
* @version 1.0
* * 1. 这个程序用于实现Spring的一个简单容器机制
* * 2. 后面我们还会详细的实现
* * 3. 这里我们实现如何将beans.xml文件进行解析,并生成对象,放入容器中
* * 4. 提供一个方法 getBean(id) 返回对应的对象
* * 5. 这里就是一个开胃小点心, 理解Spring容器的机制
*/
public class LingHuApplication {
private ConcurrentHashMap<String, Object> ioc =
new ConcurrentHashMap<>();
public LingHuApplication(String iocBeanXmlFile) throws MalformedURLException, DocumentException, ClassNotFoundException, InstantiationException, IllegalAccessException {
String path = this.getClass().getResource("/").getPath();
// System.out.println("path="+path);
//得到一个解析器
SAXReader saxReader = new SAXReader();
//老师的代码技巧->debug 看看document对象的属性
//分析了document对象的底层结构
Document document = saxReader.read(new File(path+iocBeanXmlFile));
//1. 得到rootElement, 你是OOP
Element rootElement = document.getRootElement();
//2. 得到第一个bean-monster01
Element bean = (Element) rootElement.elements("bean").get(0);
//获取到第一个bean-monster01的相关属性
String id = bean.attributeValue("id");
String classFullPath = bean.attributeValue("class");
List<Element> property = bean.elements("property");
System.out.println("id="+id);
System.out.println("classFullPath="+classFullPath);
//获取bean对象中的property属性值-id和name
String name = property.get(1).attributeValue("value");
String monsterId = property.get(0).attributeValue("value");
System.out.println("name="+name);
System.out.println("id="+monsterId);
//使用反射创建对象
Class<?> aClass = Class.forName(classFullPath);
//o对象就是monster对象
Monster o = (Monster) aClass.newInstance();
// System.out.println("o="+o);
o.setId(Integer.valueOf(monsterId));
o.setName(name);
//将创建好的对象放入到ioc对象中
ioc.put(id,o);
}
//提供一个getBean(id)返回对应的bean对象
public Object getBean(String id){
return ioc.get(id);
}
}
Gitee: "Manual Development-Simple Spring XML Configuration-based Program"