Spring工厂的实现——XML文件的加载过程

本文介绍如何从零开始构建一个简易版的Spring IoC容器,涵盖配置文件读取、XML解析、BeanDefinition创建及对象实例化过程。通过类路径读取配置文件,利用DOM解析XML,将bean信息封装至BeanDefinition,最终基于反射技术创建实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

大致思路

1.通过类路径读取配置文件beans.xml(IO),获取流对象

2.解析流对象(读取xml文件中的内容)

3.将XML文件中的bean标签信息封装到BeanDefinition对象

4.多个bean,再将BeanDefinition封装到map

5.基于xml配置构建对象实例,并存储到instanceMap

6.定义getBean方法,对外提供访问实例的方式

各类包~
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
//>>调用类加载器从类路径读取文件
//>>创建parse方法解析IO流
//模拟spring工厂的一种实现
public class ClassPathXmlApplicationContext {
    //存储bean的配置信息
    private Map<String,BeanDefinition> beanMap=
           new HashMap<>();
    //基于此map存储Bean对象
    private Map<String,Object> instanceMap=
            new HashMap<>();
    
    public ClassPathXmlApplicationContext(
            String file) throws Exception{
        //1.读取文件(IO):调用类加载器从类路径读取
         InputStream in=
         this.getClass().getClassLoader()
        .getResourceAsStream(file);
        //2.解析文件(Xml解析对象):解析流
         parse(in);
    }
//>>解析xml,借助JAVA中自带的API进行解析(parse方法的实现)
private void parse(InputStream in)throws  Exception{
        //1.创建DocumentBuilderFactory对象
        DocumentBuilderFactory factory=
        DocumentBuilderFactory.newInstance();
        //2.创建DocumentBuilder对象
        DocumentBuilder builder=
        factory.newDocumentBuilder();
        //3.创建Document对象(此对象对应是xml文件)
        Document doc=builder.parse(in);
        //4.读取document文件中的内容,...
        processDocument(doc);
        //document可以理解为xml文件在内容中的映射
    }
//>>读取bean元素中的属性并将其封装到BeanDefinition对象
 private BeanDefinition  processBeanAttrs(NamedNodeMap nMap) {
        BeanDefinition bd=new BeanDefinition();
        for(int j=0;j<nMap.getLength();j++){

            Node attrNode=nMap.item(j);//获取一个属性
            String  nodeName=attrNode.getNodeName();//获取属性名

            if(nodeName.equalsIgnoreCase("id")){
                bd.setId(attrNode.getNodeValue());
            }else  if(nodeName.equalsIgnoreCase("class")){
                bd.setClassName(attrNode.getNodeValue());
            }else  if(nodeName.equalsIgnoreCase("lazy")){
                bd.setLazy(Boolean.valueOf(attrNode.getNodeValue()));
            }
        }
        return bd;
    }
//>>基于反射技术构建类的实例对象
    private Object newInstance(String  className)throws Exception{
        Class<?> cls=Class.forName(className);
        Constructor<?>  con=cls.getDeclaredConstructor();
        con.setAccessible(true);
        Object obj=con.newInstance();
        return obj;
    }
//>>提供getBean();从容器获取对象实例
   @SuppressWarnings("unchecked")
    public <T>T getBean(String id,Class<T> cls){
        //1.从Bean的实例map中获取对象,有则直接返回
        Object obj=instanceMap.get(id);
        if(obj!=null)return (T)obj;
        //2.实例map容器中没有对象,则基于配置信息创建对象
        BeanDefinition bd=beanMap.get(id);
        try{
        obj=newInstance(bd.getClassName());
        //3.将新创建的实例对象存储到实例map容器
        instanceMap.put(bd.getId(), obj);
        }catch(Exception e){e.getMessage();};
        return (T)obj;
    }
    
}
最后附上BeanDifinition实体类代码
/**
* 通过此对象存储beans.xml文件中bean的定义信息
*/
public class BeanDefinition {
    private String id;
    private String className;
    private Boolean lazy=false;
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getClassName() {
        return className;
    }
    public void setClassName(String className) {
        this.className = className;
    }
    public Boolean getLazy() {
        return lazy;
    }
    public void setLazy(Boolean lazy) {
        this.lazy = lazy;
    }
    @Override
    public String toString() {
        return "BeanDefinition [id=" + id + ",  className=" + className + ", lazy=" + lazy +  "]";
    }
     
}
以及测试类
import java.util.Date;

public class TestSpring01 {
    public static void main(String[] args)
            throws Exception{
        ClassPathXmlApplicationContext ctx=
        new ClassPathXmlApplicationContext(
                        "beans.xml");
        Date date=ctx.getBean("date",  Date.class);
        System.out.println(date);
        Configuration c=
        ctx.getBean("cfg", Configuration.class);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值