Spring Ioc底层原理代码详细解释

概要

文章是看楠哥的视频做的总结,加上自己一些补充,为了方便以后的复习
视频地址

Spring ioc核心技术
xml解析和反射

根据需求编写XML文件,配置需要创建的bean

实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Car {
    private Integer num;
    private String brand;
}

xml文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="car1" class="network.hylnetwork.entity.Car">
        <property name="num" value="1"></property>
        <property name="brand" value="奥迪"></property>
    </bean>
    <bean id="car2" class="network.hylnetwork.entity.Car">
        <property name="num" value="2"></property>
        <property name="brand" value="奥拓"></property>
    </bean>
</beans>

编写程序读取XML文件,获取bean相关信息,类,属性,id

前提知识点Dom4j

DOM4J简介
DOM4J是 dom4j.org 出品的一个开源 XML 解析包。DOM4J应用于 Java 平台,采用了 Java 集合框架并完全支持 DOM,SAX 和 JAXP。

DOM4J 使用起来非常简单。只要你了解基本的 XML-DOM 模型,就能使用。

Dom:把整个文档作为一个对象。

DOM4J 最大的特色是使用大量的接口。

了解更多参考:Dom4j完整教程详解

导入dom4j依赖

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

仿写ClassPathXmlApplicationContext实现ApplicationContext

public class MyClassPathXmlApplicationContext implements ApplicationContext{

}

实现ApplicationContext的方法
在这里插入图片描述
测试能否获取xml文件,在MyClassPathXmlApplicationContext添加无参构造和parseXMl方法

 public MyClassPathXmlApplicationContext(String path){
        parseXML(path);
    }
    public void  parseXML(String path){
        SAXReader saxReader = new SAXReader();
        try {
            Document document = saxReader.read("src/main/resources/"+path);//看提示
            System.out.println(document);
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }

测试类

public class Test {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new MyClassPathXmlApplicationContext("spring-ioc.xml");
    }
}

成功获取xml文件,也就是我们获取到了spring-ioc.xml文件,如下运行结果在这里插入图片描述提示因为路径不完整,需要手动拼接不完整部分项目路径,否则就会出现如下错误)可以看到缺少了“src/main/resources/”部分,所以我们手动拼接上

org.dom4j.DocumentException: G:\AllSpace\IdeaSpace\Spring\spring-ioc.xml (系统找不到指定的文件。) Nested exception: G:\AllSpace\IdeaSpace\Spring\spring-ioc.xml (系统找不到指定的文件。

获取根节点,也就是我们xml文件中的beans

 public void  parseXML(String path){
        SAXReader saxReader = new SAXReader();
        try {
            Document document = saxReader.read("src/main/resources/"+path);//看提示
            Element rootElement = document.getRootElement();
            System.out.println(rootElement);
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }

运行结果如下
在这里插入图片描述

xml解析就像剥洋葱一样,是一层一层往下走的
获取根节点的迭代器,其实也就是为了得到beans中的bean

 public void  parseXML(String path){
        SAXReader saxReader = new SAXReader();
        try {
            Document document = saxReader.read("src/main/resources/"+path);//看提示
            Element rootElement = document.getRootElement();
            Iterator<Element> rootIter = rootElement.elementIterator();//根节点迭代器
            while (rootIter.hasNext()){
                Element bean = rootIter.next();//获取bean
                System.out.println(bean);
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }

运行结果如下
将beans中的两个bean都获取到了在这里插入图片描述在这里插入图片描述
获取到bean之后就是获取bean的类、属性、id信息

  public void  parseXML(String path){
        SAXReader saxReader = new SAXReader();
        try {
            Document document = saxReader.read("src/main/resources/"+path);//看提示
            Element rootElement = document.getRootElement();
            Iterator<Element> rootIter = rootElement.elementIterator();//根节点迭代器
            while (rootIter.hasNext()){
                Element bean = rootIter.next();//获取bean
                String idstr = bean.attributeValue("id");  //获取bean中的id
                String className = bean.attributeValue("class");  //获取bean中的class
                System.out.println(idstr);
                System.out.println(className);
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }

结果如下
在这里插入图片描述
可以看到和xml配置文件中的信息相匹配
在这里插入图片描述
获取属性 也就是bean中的property

  给属性赋值
                Iterator<Element> beanIter = bean.elementIterator();
                while (beanIter.hasNext()){
                    Element property = beanIter.next();
                    System.out.println(property);
                }

结果如下
在这里插入图片描述
对应了四个property
在这里插入图片描述

根据第二步获取到的信息,结合反射机制动态创建对象,同时完成属性赋值

//              反射动态创建对象
                Class clazz = Class.forName(className);
                Constructor constructor = clazz.getConstructor();

将创建好的bean存入到Map集合,设置key-value映射

  private Map<String,Object> iocMap; //创建map集合

    public MyClassPathXmlApplicationContext(String path){
        iocMap = new HashMap<>(); 
        parseXML(path);
    }
    public void  parseXML(String path){
        SAXReader saxReader = new SAXReader();
        try {
            Document document = saxReader.read("src/main/resources/"+path);//看提示
            Element rootElement = document.getRootElement();
            Iterator<Element> rootIter = rootElement.elementIterator();//根节点迭代器
            while (rootIter.hasNext()){
                Element bean = rootIter.next();//获取bean
                String idstr = bean.attributeValue("id");  //获取bean中的id
                String className = bean.attributeValue("class");  //获取bean中的class
//              反射动态创建对象
                Class clazz = Class.forName(className);
                Constructor constructor = clazz.getConstructor();
                Object object = constructor.newInstance();
                iocMap.put(idstr,object); //将bean存入map集合中,设置key-value映射
            }
        } catch (DocumentException | ClassNotFoundException | NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

提供方法从Map中通过id获取到对象的value

修改getBean方法

  @Override
    public Object getBean(String s) throws BeansException {
        return iocMap.get(s);
    }

测试类

public class Test {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new MyClassPathXmlApplicationContext("spring-ioc.xml");
        Object car1 = applicationContext.getBean("car1");
        System.out.println(car1);
    }
}

运行结果如下
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值