手撕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.xml

<bean id="car" class="com.lmh.entity.Car">
    <property name="num" value="1"></property>
    <property name="brand" value="奥迪"></property>
</bean>
<bean id="car2" class="com.lmh.entity.Car">
    <property name="num" value="2"></property>
    <property name="brand" value="大奔"></property>
</bean>

pom.xml

<dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.20</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>5.2.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>5.3.20</version>
        </dependency>

        <!--  dom4j方法-->
        <dependency>
            <groupId>dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>1.6.1</version>
        </dependency>
    </dependencies>

仿照ClassPathXmlApplicationContext类。自己建一个 MyClassPathXmlApplicationContext
在这里插入图片描述


public class MyClassPathXmlApplicationContext implements ApplicationContext {

    private Map<String, Object> ioc;

    //处理传进来的spring.xml文档
    public MyClassPathXmlApplicationContext(String path) {
        ioc = new HashMap<>();
        //解析xml
        parseXML(path);
    }

    //解析xml的方法
    public void parseXML(String path) {
        SAXReader saxReader = new SAXReader();
        try {
            //spring.xml文档,转成了Document对象
            Document document = saxReader.read("src/main/resources/" + path);
            //根节点  相当于beans
            Element rootElement = document.getRootElement();
            //根节点迭代器
            Iterator<Element> rootIter = rootElement.elementIterator();
            while (rootIter.hasNext()) {
                //得到bean
                Element bean = rootIter.next();
                //key
                String id = bean.attributeValue("id");
                String className = bean.attributeValue("class");
                //System.out.println("bean的id是:" + id + "。bean的className是:" + className);

                //反射动态创建对象
                Class clazz = Class.forName(className);
                //通过无参
                Constructor constructor = clazz.getConstructor();
                // System.out.println("class:" + clazz);
                // System.out.println("构造器:" + constructor);

                //拿到对象 , value
                Object object = constructor.newInstance();
                // System.out.println(object);

                //属性迭代器,给属性赋值
                Iterator<Element> beanIter = bean.elementIterator();
                while (beanIter.hasNext()) {
                    Element property = beanIter.next();
                    //拿到key和value 就是name和值 num1 brand奥迪   num2 brand大奔
                    String propertyName = property.attributeValue("name");
                    String propertyValue = property.attributeValue("value");
                    //System.out.println(propertyName+propertyValue);

                    //获取set方法
                    // num -- setNum, brand --setBrand
                    //切片
                    String methodName = "set" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
                    //拿到,属性类型,set方法要传参
                    Field field = clazz.getDeclaredField(propertyName);
                    //方法名,参数类型
                    Method method = clazz.getMethod(methodName, field.getType());
                    Object value = propertyValue;
                    //类型转换。 根据实体类 的类型选择转换为Integer类型
                    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);
                    System.out.println(method);
                    //调用方法
                }
                //然后用getBean方法返回出去
                ioc.put(id, object);
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } 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();
        }
    }
  @Override
    public Object getBean(String name) throws BeansException 	{
        //通过map的key 得到 value并返回
        return ioc.get(name);
    }	

在这里插入图片描述

Test

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值