前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring Ioc底层实现

Spring Ioc底层实现

作者头像
长安不见使人愁
发布2022-10-25 19:24:22
2970
发布2022-10-25 19:24:22
举报
文章被收录于专栏:给时光以生命

原理和步骤

  1. Ioc容器的实现主要依赖的是xml解析和Java反射。
  2. 步骤:读取配置文件 -> 将其逐层“剥开”,获取各项属性 -> 通过各属性配合反射生成对象 -> 将其放入容器中,以供调用

具体实现

  • 实体类 Book
代码语言:javascript
复制
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Book {
    private Integer id;
    private String name;
    private Double price;
}
  • 配置文件 spring.xml
代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       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="threeBody" class="per.tan.ioc.Book">
        <property name="id" value="1"/>
        <property name="name" value="《三体》"/>
        <property name="price" value="59.9"/>
    </bean>
</beans>
  • xml解析使用的是Dom4j,加入maven依赖
代码语言:javascript
复制
<dependency>
    <groupId>dom4j</groupId>
    <artifactId>dom4j</artifactId>
    <version>1.1</version>
</dependency>

MyClassPathXmlApplicationContext。需要实现接口ApplicationContext,着重重写以下方法:

  • 创建容器 Map
代码语言:javascript
复制
private final Map<String, Object> iocMap;
  • 重写构造方法 此处将解析xml的步骤写在自定义方法parseXML
代码语言:javascript
复制
public MyClassPathXmlApplicationContext(String path) {
    iocMap = new HashMap<>();
    parseXML(path);
}
  • parseXML()
代码语言:javascript
复制
//使用Dom4j进行xml解析
public void parseXML(String path) {
    SAXReader saxReader = new SAXReader();
    try {
        //定义文档
        Document document = saxReader.read("src/main/resources/" + path);
        //获取根节点,即<beans>
        Element beans = document.getRootElement();
        //beans迭代器
        Iterator<Element> beansIterator = beans.elementIterator();
        while (beansIterator.hasNext()) {
            Element bean = beansIterator.next();
            String idStr = bean.attributeValue("id");
            String classStr = bean.attributeValue("class");

            Class<?> clazz = Class.forName(classStr);
            Constructor<?> constructor = clazz.getConstructor();
            //利用获取到的无参构造生成目标对象
            Object object = constructor.newInstance();
            //bean迭代器
            Iterator<Element> beanIterator = bean.elementIterator();
            while (beanIterator.hasNext()) {
                Element property = beanIterator.next();
                //获取属性
                String propertyName = property.attributeValue("name");
                String propertyValue = property.attributeValue("value");
                Field field = clazz.getDeclaredField(propertyName);
                //获取方法
                String methodStr = "set" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
                Method method = clazz.getMethod(methodStr, field.getType());

                Object value = propertyValue;
                //判断属性类型并转换
                switch (field.getType().getName()) {
                    case "java.lang.Integer":
                        value = Integer.parseInt(propertyValue);
                        break;
                    case "java.lang.Double":
                        value = Double.parseDouble(propertyValue);
                        break;
                }
                method.invoke(object, value);
            }
            //装入容器
            iocMap.put(idStr, object);
        }
    } catch (DocumentException e) {
        e.printStackTrace();
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    }
}
  • 重写getBean,根据名字从容器中获取bean
代码语言:javascript
复制
 @Override
 public Object getBean(String s) throws BeansException {
     return iocMap.get(s);
 } 

测试 Test

代码语言:javascript
复制
public class Test {
public static void main(String[] args) {
   ApplicationContext context = new MyClassPathXmlApplicationContext("spring.xml");
   Book book = (Book) context.getBean("threeBody");
   System.out.println(book);
 }
}
  • 成果
代码语言:javascript
复制
D:\Java_JDK\JDK8\bin\java.exe ...
Book(id=1, name=《三体》, price=59.9)

Process finished with exit code 0

Q.E.D.

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 原理和步骤
  • 具体实现
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档