模拟 Spring IOC 容器 Bean 对象实例化

Spring IOC 容器 Bean对象实例化模拟

思路:
1.定义Bean 工厂接口,提供获取bean方法
2.定义Bean工厂接口实现类,解析配置文件,实例化Bean对象
3.实现获取Bean方法

新建Maven项目

1.创建Maven的普通java项目
在这里插入图片描述
2.设置项目的坐标、名称、工作空间
在这里插入图片描述
3.设置项目的 Maven 环境
在这里插入图片描述

定义 Bean 属性对象

package com.xxxx.po;

/**
 * Bean对象
 * 用来接收配置文件(spring.xml)中,bean标签的id和class属性值
 */
public class MyBean {
    
    

    private String id;//bean标签的id属性
    private String clazz;//bean标签的class属性

    public MyBean() {
    
    
    }

    public MyBean(String id, String clazz) {
    
    
        this.id = id;
        this.clazz = clazz;
    }

    public String getId() {
    
    
        return id;
    }

    public void setId(String id) {
    
    
        this.id = id;
    }

    public String getClazz() {
    
    
        return clazz;
    }

    public void setClazz(String clazz) {
    
    
        this.clazz = clazz;
    }

}

添加 dom4j 和 XPath 坐标依赖

        <!-- dom4j -->
        <dependency>
            <groupId>dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>1.6.1</version>
        </dependency>

        <!-- XPath -->
        <dependency>
            <groupId>jaxen</groupId>
            <artifactId>jaxen</artifactId>
            <version>1.1.6</version>
        </dependency>

准备自定义配置文件

spring.xml

<?xml version="1.0" encoding="UTF-8" ?>
<beans>

    <bean id="userService" class="com.xxxx.service.UserService"/>
    <bean id="userDao" class="com.xxxx.dao.UserDao"/>
    
</beans>

定义 Bean 工厂接口

package com.xxxx.factory;

/**
 * 工厂接口
 * 定义获取bean对象的方法接口
 */
public interface MyFactory {
    
    
    //通过id属性获取bean对象
    public Object getBean(String id);
}

定义 Bean 接口的实现类

package com.xxxx.factory;

import com.xxxx.po.MyBean;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;

import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 工厂接口的实现类
 *  1.获取要解析的配置文件
 *  2.解析配置文件(dom4j),将解析好的bean标签设置到对应的bean对象中,再将bean对象设置到集合中
 *  3.得到集合中的Bean对象,并将对应的id与其实例化好的Bean设置到map中
 *
 */
public class MyClassPathXmlApplication implements MyFactory{
    
    

    private List<MyBean> beanList = null;//存放解析好的bean标签集合
    private Map<String ,Object> beanMap = new HashMap<>();//实例化好的bean对象放入map

    //获取要解析的配置文件
    //通过带参构造器得到相关配置文件
    public MyClassPathXmlApplication(String fileName){
    
    

        //解析配置文件,将结果设置到list中
        this.parseXml(fileName);

        //实例化Bean对象,将结果设置到map中
        this.instanceBean();

    }



    /**
     * 解析XML配置文件
     * @param fileName
     */
    private void parseXml(String fileName) {
    
    
        //获取解析器
        SAXReader saxReader = new SAXReader();
        //得到要解析的配置文件的url
        URL url = this.getClass().getClassLoader().getResource(fileName);

        try {
    
    
            //通过解析器解析xml文件(spring.xml),返回Document对象
            Document document = saxReader.read(url);
            //通过xpath语法,获取beans标签下的所有bean标签
            XPath xPath = document.createXPath("beans/bean");
            //通过XPath语法获取要解析的指定元素
            List<Element> elementList = xPath.selectNodes(document);
            //判断标签集合是否存在
            if(elementList != null && elementList.size()>0){
    
    
                //实例化集合
                beanList= new ArrayList<>();
                //遍历集合
                for(Element el : elementList){
    
    
                    //获取元素的id属性值和class属性值
                    String id = el.attributeValue("id");
                    String clazz = el.attributeValue("class");
                    //将id和clazz的值设置到对应的bean对象中
                    MyBean myBean = new MyBean(id,clazz);
                    //将对应的bean对象设置到集合中
                    beanList.add(myBean);
                }
            }
        } catch (DocumentException e) {
    
    
            e.printStackTrace();
        }

    }

    /**
     * 实例化Bean对象
     * 1.得到对应的bean对象中的id和class
     * 2.通过class属性值(类路径)得到对应的实例化对象
     * 3.将id和实例化的对象分别设置到map的键和值中
     */
    private void instanceBean() {
    
    
        //判断bean对象的集合是否存在
        if(beanList != null && beanList.size()>0){
    
    
            //遍历
            for(MyBean bean : beanList){
    
    
                try {
    
    
                    //键
                    String id = bean.getId();
                    //值(实例化好的对象)
                    //通过class的值(类路径)得到实例化对象
                    Object object = Class.forName(bean.getClazz()).newInstance();
                    //设置map
                    beanMap.put(id,object);
                } catch (Exception e) {
    
    
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 通过id获取map中指定的实例化对象
     * @param id
     * @return
     */
    @Override
    public Object getBean(String id) {
    
    
        return beanMap.get(id);
    }
}

创建与配置文件中对应的 Bean 对象

UserService.java

package com.xxxx.service;

public class UserService {
    
    
    public void test(){
    
    
        System.out.println("UserService...");
    }
}

UserDao.java

package com.xxxx.dao;

public class UserDao {
    
    
    public void test(){
    
    
        System.out.println("UserDao...");
    }
}

测试是否可以获取实例化的Bean对象

package com.xxxx;

import com.xxxx.dao.UserDao;
import com.xxxx.factory.MyClassPathXmlApplication;
import com.xxxx.factory.MyFactory;
import com.xxxx.service.UserService;

/**
 * 模拟Spring IOC 容器 Bean对象实例化
 */
public class App {
    
    
    public static void main(String[] args) {
    
    
        //得到上下文环境
        MyFactory factory = new MyClassPathXmlApplication("spring.xml");

        //得到实例化好的对象
        UserService userService = (UserService) factory.getBean("userService");
        UserDao userDao = (UserDao) factory.getBean("userDao");

        UserDao userDao2 = (UserDao) factory.getBean("userDao");
        System.out.println(userDao);
        System.out.println(userDao2);

        userService.test();
        userDao.test();
    }
}

测试结果

com.xxxx.dao.UserDao@4e515669
com.xxxx.dao.UserDao@4e515669
UserService...
UserDao...

Guess you like

Origin blog.csdn.net/lln1540295459/article/details/121065161