Spring框架原理

手写Spring框架

1 如何理解Spring中两个map

  1. 一个map用于存储bean的配置信息
  2. 一个map用于存储bean的实例信息

2.编写代码

1.创建BeanDefinition类用来存储配置文件信息

public class BeanDefinition implements Serializable {
    private String id;
    private String pkgClass;
    private Boolean lazy;

    //get set toString

}

2.创建配置文件 spring-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans>
    <bean id="date" class="java.util.Date" lazy="true"/>
    <bean id="obj" class="java.lang.Object" lazy="false"/>
</beans>

3.创建ClassPathXmlApplicationContext类用于读取配置文件并创建对象

/**
 * @Author: Rwenjie
 * @ProjectName: springframework
 * @Description: 用于读取配置文件并创建对象
 * @Date: 2020/7/28   16:53
 **/
public class ClassPathXmlApplicationContext {

    /*
     * 通过此map存储配置文件中定义的Bean对象的配置信息
     */

    private Map<String, BeanDefinition> beanMap = new HashMap<String, BeanDefinition>();


    /*
     * 通过此map存储Bean实例
     */

    private Map<String, Object> instanceMap = new HashMap<String, Object>();


    public ClassPathXmlApplicationContext(String file) {
        //1.读取配置文件 getClassLoader() -获取根目录
        InputStream in = getClass().getClassLoader().getResourceAsStream(file);
        //2.解析文件
        //3.分装数据
    }

    /*
     * Class<T> t:希望返回类型
     */

    public <T>T getBean(String key, Class<T> t){

        return null;
    }
}

4.成功读取配置文件并获取bean标签测试

 /**
 * @Author: Rwenjie
 * @ProjectName: springframework
 * @Description: 用于读取配置文件并创建对象
 * @Date: 2020/7/28   16:53
 **/
public class ClassPathXmlApplicationContext {

    /*
     * 通过此map存储配置文件中定义的Bean对象的配置信息
     */

    private Map<String, BeanDefinition> beanMap = new HashMap<String, BeanDefinition>();


    /*
     * 通过此map存储Bean实例
     */

    private Map<String, Object> instanceMap = new HashMap<String, Object>();


    public ClassPathXmlApplicationContext(String file) {
        //1.读取配置文件 getClassLoader() -获取根目录
        InputStream in = getClass().getClassLoader().getResourceAsStream(file);
        //2.解析文件
        try {
            parse(in);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //3.分装数据
    }


    /*
     * parse 此方法用来解析xml配置文件
     * 市场主流的xml解析 dom(标准) dom4j sax pull....
     */

    private void parse(InputStream in) throws Exception {
        //1. 创建解析器对象
        DocumentBuilder builder =
                DocumentBuilderFactory.newInstance().newDocumentBuilder();
        //2.解析流对象 导w3c下的包
        Document doc = builder.parse(in);
        //3.处理doc
        processDocument(doc);

    }


    /*
     *  processDocument 此方法用来读取配置信息
     */

    private void processDocument(Document doc){
        //1.获取所有的bean元素
        NodeList list = doc.getElementsByTagName("bean");
        //2.迭代bean元素
        for (int i=0; i<list.getLength(); i++){
            //一个Node对象接收一个bean标签
            Node node = list.item(i);
            //测试标签名是否成功
            System.out.println(node.getNodeName());
        }
    }


    /*
     * Class<T> t:希望返回类型
     */

    public <T>T getBean(String key, Class<T> t){



        return null;
    }
}

public class TestMian {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("Spring-config.xml");
    }
}
image-20200728173551633

5.得到bean标签属性的值,并存到Map中

public class ClassPathXmlApplicationContext {

    /*
     * 通过此map存储配置文件中定义的Bean对象的配置信息
     */

    private Map<String, BeanDefinition> beanMap = new HashMap<String, BeanDefinition>();


    /*
     * 通过此map存储Bean实例
     */

    private Map<String, Object> instanceMap = new HashMap<String, Object>();


    public ClassPathXmlApplicationContext(String file) {
        //1.读取配置文件 getClassLoader() -获取根目录
        InputStream in = getClass().getClassLoader().getResourceAsStream(file);
        //2.解析文件
        try {
            parse(in);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //3.分装数据
    }


    /*
     * parse 此方法用来解析xml配置文件
     * 市场主流的xml解析 dom(标准) dom4j sax pull....
     */

    private void parse(InputStream in) throws Exception {
        //1. 创建解析器对象
        DocumentBuilder builder =
                DocumentBuilderFactory.newInstance().newDocumentBuilder();
        //2.解析流对象 导w3c下的包
        Document doc = builder.parse(in);
        //3.处理doc
        processDocument(doc);

    }


    /*
     *  processDocument 此方法用来读取配置信息
     */

    private void processDocument(Document doc){
        //1.获取所有的bean元素
        NodeList list = doc.getElementsByTagName("bean");
        //2.迭代bean元素
        for (int i=0; i<list.getLength(); i++){
            //一个Node对象接收一个bean标签
            Node node = list.item(i);
            //测试标签名是否成功
            System.out.println(node.getNodeName());

            //一个Node对 BeanDefinition对象
            BeanDefinition bd = new BeanDefinition();
            //获取bean标签的属性、
            NamedNodeMap nodeMap = node.getAttributes();
            System.out.println(nodeMap.getNamedItem("id").getNodeValue());
            bd.setId(nodeMap.getNamedItem("id").getNodeValue());
            bd.setPkgClass(nodeMap.getNamedItem("class").getNodeValue());
            bd.setLazy(Boolean.valueOf(nodeMap.getNamedItem("lazy").getNodeValue()));
            //存储配置信息
            beanMap.put(bd.getId(), bd);
            System.out.println(beanMap );
        }
    }


    /*
     * Class<T> t:希望返回类型
     */

    public <T>T getBean(String key, Class<T> t){



        return null;
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JsG4cCGf-1595940665533)(F:\Typora\img\image-20200728192905052.png)]

6.判断是否延迟加载,利用反射

public class ClassPathXmlApplicationContext {

    /*
     * 通过此map存储配置文件中定义的Bean对象的配置信息
     */

    private Map<String, BeanDefinition> beanMap = new HashMap<String, BeanDefinition>();


    /*
     * 通过此map存储Bean实例
     */

    private Map<String, Object> instanceMap = new HashMap<String, Object>();


    public ClassPathXmlApplicationContext(String file) {
        //1.读取配置文件 getClassLoader() -获取根目录
        InputStream in = getClass().getClassLoader().getResourceAsStream(file);
        //2.解析文件
        try {
            parse(in);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //3.分装数据
    }


    /*
     * parse 此方法用来解析xml配置文件
     * 市场主流的xml解析 dom(标准) dom4j sax pull....
     */

    private void parse(InputStream in) throws Exception {
        //1. 创建解析器对象
        DocumentBuilder builder =
                DocumentBuilderFactory.newInstance().newDocumentBuilder();
        //2.解析流对象 导w3c下的包
        Document doc = builder.parse(in);
        //3.处理doc
        processDocument(doc);

    }


    /*
     *  processDocument 此方法用来读取配置信息
     */

    private void processDocument(Document doc) throws Exception {
        //1.获取所有的bean元素
        NodeList list = doc.getElementsByTagName("bean");
        //2.迭代bean元素
        for (int i=0; i<list.getLength(); i++){
            //一个Node对象接收一个bean标签
            Node node = list.item(i);
            //测试标签名是否成功
            System.out.println(node.getNodeName());

            //一个Node对 BeanDefinition对象
            BeanDefinition bd = new BeanDefinition();
            //获取bean标签的属性、
            NamedNodeMap nodeMap = node.getAttributes();
            System.out.println(nodeMap.getNamedItem("id").getNodeValue());
            bd.setId(nodeMap.getNamedItem("id").getNodeValue());
            bd.setPkgClass(nodeMap.getNamedItem("class").getNodeValue());
            bd.setLazy(Boolean.valueOf(nodeMap.getNamedItem("lazy").getNodeValue()));
            //存储配置信息
            beanMap.put(bd.getId(), bd);

            //基于配置信息中lazy属性的值判断是否延迟加载
            if(!bd.getLazy()){
                Object object = newBeanIntance(bd.getPkgClass());
                instanceMap.put(bd.getId(), object);

            }
        }
        System.out.println(beanMap );
    }

    /*
     * 此方法用来反射创建对象
     */

    private Object newBeanIntance(String pkgClass) throws Exception{
        Class<?> cls = Class.forName(pkgClass);
        //找到无参构造方法创建对象
        Constructor<?> con = cls.getDeclaredConstructor(null);
        //如果构造函数私有化也可以起执行
        con.setAccessible(true);
        //通过无参构造函数创建对象
        return con.newInstance();
    }


    /*
     * Class<T> t:希望返回类型
     */

    public <T>T getBean(String key, Class<T> t){


        return null;
    }
}

7.编写getBean方法用来返回对象

 public <T>T getBean(String key, Class<T> t) {

        try {
            //1.判断当前instanceMap中是否有Bean的实例
            Object object = instanceMap.get(key);
            if(object!=null){
                return (T)object;
            }
            //2.实例map中没有对象则创建对象,然后存储到map
            object = newBeanInstance(t.getName());
            System.out.println(t.getName());
            instanceMap.put(key, object);
            return (T)object;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

8.获取对象

public class TestMian {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("Spring-config.xml");
        Object obj = ac.getBean("obj", Object.class);
        Date date = ac.getBean("date", Date.class);

        System.out.println(obj);
        System.out.println(date);

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值