手写spring 框架——第二篇(依赖注入)

简介: 手写spring 框架——第二篇(依赖注入)

属性注入

1.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<beans>
    <bean id="person" class="com.jd.xq.spring.bean.Person">
        <property name="name" value="xq"></property>
        <property name="age" value="10"></property>
    </bean>
</beans>

2.属性类

package com.jd.xq.spring.bean;
/**
 * @author duanxiaoqiu
 * @Date 2019-12-27 12:10
 **/
public class PropertyDefinition {
    private String name;
    private String value;
    public PropertyDefinition(String name, String value) {
        this.name = name;
        this.value = value;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getValue() {
        return value;
    }
    public void setValue(String value) {
        this.value = value;
    }
}

3.修改bean

public class BeanDefinition {
    private String id;//bean的id
    private String className;//bean的类
    private List<PropertyDefinition> propertyDefinitions=new ArrayList<PropertyDefinition>();
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getClassName() {
        return className;
    }
    public void setClassName(String className) {
        this.className = className;
    }
    public BeanDefinition(String id, String className) {
        this.id = id;
        this.className = className;
    }
    public List<PropertyDefinition> getPropertyDefinitions() {
        return propertyDefinitions;
    }
    public void setPropertyDefinitions(List<PropertyDefinition> propertyDefinitions) {
        this.propertyDefinitions = propertyDefinitions;
    }
}

4.修改读取xml,读取属性信息

/**
     * 根据文件名读取xml的配置文件
     *
     */
    private void readXml(String fileName) {
        // TODO Auto-generated method stub
        //创建一个读取器
        SAXReader saxReader = new SAXReader();
        Document document = null;
        try {
            //获取要读取的配置文件的路径
            URL xmlPath = this.getClass().getClassLoader().getResource(fileName);
            //读取文件内容
            document = saxReader.read(xmlPath);
            //获取xml中的根元素
            Element rootElement = document.getRootElement();
            for (Iterator iterator = rootElement.elementIterator(); iterator.hasNext(); ) {
                Element element = (Element) iterator.next();
                String id = element.attributeValue("id");//获取bean的id属性值
                String clazz = element.attributeValue("class");//获取bean的class属性值
                BeanDefinition beanDefinition = new BeanDefinition(id, clazz);
                //获取bean的Property属性
                for (Iterator subElementIterator = element.elementIterator(); subElementIterator.hasNext(); ) {
                    Element subElement = (Element) subElementIterator.next();
                    String propertyName = subElement.attributeValue("name");
                    String propertyValue = subElement.attributeValue("value");
                    PropertyDefinition propertyDefinition = new PropertyDefinition(propertyName, propertyValue);
                    beanDefinition.getPropertyDefinitions().add(propertyDefinition);
                }
                beanDefines.add(beanDefinition);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

5.属性注入

/**
     * 为bean对象的属性注入值
     * <p>
     */
    private void injectObject() {
        //遍历配置文件中定义的所有的bean
        for (BeanDefinition beanDefinition : beanDefines) {
            //找到要注入的bean
            Object bean = sigletons.get(beanDefinition.getId());
            if (bean != null) {
                try {
                    BeanInfo info = Introspector.getBeanInfo(bean.getClass());//通过类Introspector的getBeanInfo方法获取对象的BeanInfo 信息
                    //通过BeanInfo来获取属性的描述器(PropertyDescriptor),通过这个属性描述器就可以获取某个属性对应的getter/setter方法,然后我们就可以通过反射机制来调用这些方法。
                    PropertyDescriptor[] pds = info.getPropertyDescriptors();//获得 bean所有的属性描述
                    //遍历要注入的bean的所有属性
                    for (PropertyDefinition propertyDefinition : beanDefinition.getPropertyDefinitions()) {
                        //遍历要注入bean通过属性描述器得到的所有属性以及行为
                        for (PropertyDescriptor propertyDescriptor : pds) {
                            //用户定义的bean属性与java内省后的bean属性名称相同时
                            if (propertyDefinition.getName().equals(propertyDescriptor.getName())) {
                                Method setter = propertyDescriptor.getWriteMethod();//获取属性的setter方法
                                //取到了setter方法
                                if (setter != null) {
                                    Object value = null;//用来存储引用的值
                                    //ConvertUtil依赖两个jar包,一个是common-beanutils,而common-beanutils又依赖common-logging
                                    //ConvertUtil将任意类型转化为需要的类型
                                    value = ConvertUtils.convert(propertyDefinition.getValue(), propertyDescriptor.getPropertyType());
                                    setter.setAccessible(true);//保证setter方法可以访问私有
                                    try {
                                        setter.invoke(bean, value);//把引用对象注入到属性
                                    } catch (Exception e) {
                                        e.printStackTrace();
                                    }
                                }
                                break;//找到了注入的属性后,跳出循环
                            }
                        }
                    }
                } catch (IntrospectionException e) {
                    e.printStackTrace();
                }
            }
        }
    }

6.测试

代码:

https://github.com/zhugezifang/my-spring-framework


相关文章
|
16天前
|
存储 安全 Java
事件的力量:探索Spring框架中的事件处理机制
事件的力量:探索Spring框架中的事件处理机制
28 0
|
26天前
|
缓存 Java Spring
Spring 框架中 Bean 的生命周期
Spring 框架中 Bean 的生命周期
33 1
|
1月前
|
开发框架 安全 Java
Spring 框架:企业级应用开发的强大工具
在当今数字化时代,企业级应用开发的需求日益增长。为了满足这一需求,开发者们需要一款功能强大、易于使用的开发框架。Spring 框架作为 Java 领域的领先者,为企业级应用开发提供了全面的解决方案。本文将深入探讨 Spring 框架的各个方面,包括其历史、核心模块、优势以及应用场景。
24 0
|
1月前
|
开发框架 Java Spring
Spring依赖注入以及使用建议
Spring依赖注入以及使用建议
31 0
|
1月前
|
存储 Java 数据库
|
1月前
|
人工智能 JSON 前端开发
【Spring boot实战】Springboot+对话ai模型整体框架+高并发线程机制处理优化+提示词工程效果展示(按照框架自己修改可对接市面上百分之99的模型)
【Spring boot实战】Springboot+对话ai模型整体框架+高并发线程机制处理优化+提示词工程效果展示(按照框架自己修改可对接市面上百分之99的模型)
|
2月前
|
XML Java 程序员
Spring的依赖注入
Spring的依赖注入
|
2月前
|
缓存 安全 Java
Shiro框架以及Spring Boot整合Shiro
Shiro框架以及Spring Boot整合Shiro
Shiro框架以及Spring Boot整合Shiro
|
1月前
|
Java 数据库连接 API
【Spring】1、Spring 框架的基本使用【读取配置文件、IoC、依赖注入的几种方式、FactoryBean】
【Spring】1、Spring 框架的基本使用【读取配置文件、IoC、依赖注入的几种方式、FactoryBean】
49 0
|
1天前
|
Java Spring
Spring Boot脚手架集成校验框架
Spring Boot脚手架集成校验框架
6 0