Manual development - simple Spring XML configuration-based program - source code analysis

Manual development-simple Spring XML configuration-based program

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 ClassPathXmlApplicationContextget the container, the container automatically reads the beans.xml configuration file, we get the object iocthrough the container method, and output the object.getBean

img

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 iocmapping ConcurrentHashMapthat stores object name id and object.
  • Create a constructor and place all the following operations in this constructor
  • Use xmlparsing technology dom4jto beans.xmlread the information in the file and obtain the attribute values ​​of the node information.
  • Create objects using reflection
  • Place the object iocinto
  • provide a getBeanmethod

When using xml parsing technology dom4jto 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, targetthe path in the working directory. Our beans.xml file is placed resourcein the directory. After compilation, it will run to the target/classes directory, so here The directory we dom4jread 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 documentthe 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.

img

        Class<?> aClass = Class.forName(classFullPath);
        Monster o = (Monster) aClass.newInstance();
        o.setId(Integer.valueOf(monsterId));
        o.setName(name);
        ioc.put(id,o);

Finally, a getBeanmethod 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);
    }

img

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 LingHuApplicationcontainer 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 ConcurrentHashMapto 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"

Guess you like

Origin blog.csdn.net/weixin_43891901/article/details/132782733