Spring依赖注入简单实现

        Spring的依赖注入(Dependency Injection,简称DI)是Spring框架的核心特性之一,它通过容器来管理对象之间的依赖关系,实现松耦合、可维护和可测试的代码设计。在Spring DI中,对象不再负责自己的依赖关系的创建和管理,而是由容器负责将依赖项注入到目标对象中。接下来我将通过解析XML文件的方式来实现依赖注入。

配置Spring.xml 

<?xml version="1.0" encoding="UTF-8"?>
<beans>
    <bean id="student" class="org.example.bean.Student">
        <property name="id" value="101"></property>
        <property name="name" value="艾克"></property>
    </bean>
    <bean id="userBean" class="org.example.bean.User">
        <property name="name" value="hong"></property>
        <property name="age" value="21"></property>
        <property name="student" ref="student"></property>
    </bean>
</beans>

 实现依赖注入

// 应用上下文接口
package org.example.myspringframework;

public interface ApplicationContext {
    Object getBean(String id);
}

// 类路径XML应用上下文,实现应用上下文接口
package org.example.myspringframework;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;

import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;

public class ClassPathXmlApplicationContext implements ApplicationContext {
    private HashMap<String, Object> containers = new HashMap<>();
    public ClassPathXmlApplicationContext(String xmlLocation) {
        try {
            SAXReader reader = new SAXReader();
            // 获取一个输入流指向配置文件
            InputStream in = ClassLoader.getSystemClassLoader().getResourceAsStream(xmlLocation);
            // 读文件
            Document document = reader.read(in);
            // 获取所有的bean标签
            List<Node> nodes = document.selectNodes("//bean");
            nodes.forEach(node -> {
                // 获取id、class属性
                Element beanElement = (Element) node;
                String id = ((Element) node).attributeValue("id");
                String className = ((Element) node).attributeValue("class");
                // 利用反射机制创建对象
                try {
                    Class<?> aClass = Class.forName(className);
                    Constructor<?> declaredConstructor = aClass.getDeclaredConstructor();
                    Object bean = declaredConstructor.newInstance();
                    containers.put(id, bean);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
            nodes.forEach(node -> {
                try {
                    Element beanElement = (Element) node;
                    String id = beanElement.attributeValue("id");
                    String className = beanElement.attributeValue("class");
                    Class<?> aClass = Class.forName(className);
                    List<Element> properties = beanElement.elements("property");
                    properties.forEach(property -> {
                        try {
                            // 获取property属性
                            String name = property.attributeValue("name");
                            Field field = aClass.getDeclaredField(name);
                            String methodName = "set" + name.toUpperCase().charAt(0) + name.substring(1);
                            Method setMethod = aClass.getDeclaredMethod(methodName, field.getType());
                            String value = property.attributeValue("value");
                            String ref = property.attributeValue("ref");
                            Object actualValue = value;
                            if (value != null) {
                                String propertyTypeSimpleName = field.getType().getSimpleName();
                                actualValue = isPrimitiveType(propertyTypeSimpleName, value, actualValue);
                                setMethod.invoke(containers.get(id), actualValue);
                            }
                            if (ref != null) {
                                setMethod.invoke(containers.get(id), containers.get(ref));
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    });
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public Object getBean(String id) {
        return containers.get(id);
    }

    private Object isPrimitiveType(String propertyTypeSimpleName, String value, Object actualValue) {
        switch (propertyTypeSimpleName) {
            case "byte":
                actualValue = Byte.parseByte(value);
                break;
            case "Byte":
                actualValue = Byte.valueOf(value);
                break;
            case "short":
                actualValue = Short.parseShort(value);
                break;
            case "Short":
                actualValue = Short.valueOf(value);
                break;
            case "int":
                actualValue = Integer.parseInt(value);
                break;
            case "Integer":
                actualValue = Integer.valueOf(value);
                break;
            case "long":
                actualValue = Long.parseLong(value);
                break;
            case "Long":
                actualValue = Long.valueOf(value);
                break;
            case "float":
                actualValue = Float.parseFloat(value);
                break;
            case "Float":
                actualValue = Float.valueOf(value);
                break;
            case "double":
                actualValue = Double.parseDouble(value);
                break;
            case "Double":
                actualValue = Double.valueOf(value);
                break;
            case "boolean":
                actualValue = Boolean.parseBoolean(value);
                break;
            case "Boolean":
                actualValue = Boolean.valueOf(value);
                break;
            case "char":
                actualValue = value.charAt(0);
                break;
            case "Character":
                actualValue = Character.valueOf(value.charAt(0));
                break;
            case "String":
                break;
        }
        return actualValue;
    }
}

// bean对象
package org.example.bean;

public class Student {
    private int id;
    private String name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

package org.example.bean;

public class User {
    private String name;
    private int age;
    private Student student;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Student getStudent() {
        return student;
    }

    public void setStudent(Student student) {
        this.student = student;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", student=" + student +
                '}';
    }
}

// 测试
import org.example.bean.User;
import org.example.myspringframework.ApplicationContext;
import org.example.myspringframework.ClassPathXmlApplicationContext;
import org.junit.Test;

public class XMLTest {
    @Test
    public void parseXMLTest() {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        Object userBean = applicationContext.getBean("userBean");
        userBean = (User) userBean;
        System.out.println(userBean);
    }
}

 运行结果:

        上述代码通过读取XML文件的方式完成依赖注入,实现思路简要概括一下,创建应用上下文接口,这里模仿springframework,创建类路径XML应用上下文实现此接口。读取XML并将每一个bean对象放入一个容器中,这里使用Map实现。此时仅完成bean对象的实例化,还未给对象的属性赋值,因而需要获取bean标签中的property标签,使用Map的get方法可以获取到bean对象,使用反射机制获取bean对象的setter方法,并将property中的value或ref作为invoke方法的参数,这样就完成了一个bean对象的初始化。依次遍历每一个bean对象即可。


        上述内容如果有错误的地方,希望大佬们可以指正。我一直在学习的路上,您的帮助使我收获更大!觉得对您有帮助的话,还请点赞支持!我也会不断更新文章!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

弘弘弘弘~

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

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

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

打赏作者

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

抵扣说明:

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

余额充值