Spring IoC底层实现

本文详细介绍了Spring IoC容器的核心实现,通过XML解析和反射机制动态创建及初始化对象,并将其存入Map中,以id为键,对象为值。通过自定义的ClassPathXmlApplicationContext类,实现了从XML配置文件加载bean并获取对象的功能。
摘要由CSDN通过智能技术生成

Spring IoC底层实现

⭐核心技术点:XML解析+反射
具体思路:

  1. 根据需求编写XML文件,配置需要创建的bean。
  2. 编写程序读取XML文件,获取bean相关信息,类、属性、id。
  3. 根据第2步获取到的信息,结合反射机制动态创建对象,同时完成属性的赋值。
  4. 将创建好的bean存入Map集合,设置key-value映射,key就是bean中的id值,value就是bean对象。
  5. 提供方法从Map通过id获取到对应的value。

⭐实现代码如下:

spring_ioc.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.0.xsd"
       xmlns:p="http://www.springframework.org/schema/p">
    <bean id="car" class="com.oyrf.entity.Car">
        <property name="num" value="1"></property>
        <property name="brand" value="宝马"></property>
        <property name="price" value="22.8"></property>
    </bean>

</beans>
△关键:自定义的ClassPathXmlApplicationContext

MyClassPathXmlApplicationContext.java(当中省略了抽象方法)

public class MyClassPathXmlApplicationContext implements ApplicationContext {
    private Map<String,Object> iocMap;

    public MyClassPathXmlApplicationContext(String path) {
        iocMap = new HashMap<>();
        //解析XML
        parseXML(path);
    }
    public void parseXML(String path){
        SAXReader saxReader = new SAXReader();
        try {
            Document document = saxReader.read("src/main/resources/"+path);
            Element root = document.getRootElement();
            Iterator<Element> rootIter = root.elementIterator();
            while (rootIter.hasNext()){
                Element bean = rootIter.next();
                String idStr = bean.attributeValue("id");
                String classStr = bean.attributeValue("class");
                //反射动态创建对象
                Class  clazz = Class.forName(classStr);
                Constructor constructor = clazz.getConstructor();
                Object object = constructor.newInstance();
                //给属性赋值
                Iterator<Element> beanIter = bean.elementIterator();
                while (beanIter.hasNext()){
                    Element property = beanIter.next();
                    String propertyName = property.attributeValue("name");
                    String propertyValue = property.attributeValue("value");
                    //获取setter方法
                    //num对应setNum,brand对应setBrand
                    String methodName = "set"+propertyName.substring(0,1).toUpperCase() + propertyName.substring(1);
                    //获取属性类型
                    Field field = clazz.getDeclaredField(propertyName);
                    Method method = clazz.getMethod(methodName,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);
                    }
                    //调用方法
                    method.invoke(object,value);
                }
                //存入Map
                iocMap.put(idStr,object);

            }
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e){

        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }
}

注意:要对其中一个抽象方法getbean()进行修改:

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

Test.java

package com.oyrf.ioc;

import com.oyrf.entity.Car;
import org.springframework.context.ApplicationContext;

public class Test {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new MyClassPathXmlApplicationContext("spring_ioc.xml");
        Car car=(Car) applicationContext.getBean("car");
        System.out.println(car);
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

OYBox

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值