021.使用反射,编写SpringIOC

什么是SpringIOC

就是把每一个bean(实体类)与bean(实体类)之间的关系交给第三方容器进行管理。 而不是传统的在你的对象内部直接控制。


SpringIOC实现原理

  • 读取bean的XML配置文件
  • 使用beanId查找bean配置,并获取配置文件中class地址
  • 使用java反射技术实例化对象
  • 获取属性配置,使用反射技术进行赋值

详细步骤:

  • 1.利用传入的参数获取xml文件的流,并且利用dom4j解析成Document对象
  • 2.对于Document对象获取根元素对象后对下面的标签进行遍历,判断是否有符合的id.
  • 3.如果找到对应的id,相当于找到了一个Element元素,开始创建对象,先获取class属性,根据属性值利用反射建立对象.
  • 4.遍历标签下的property标签,并对属性赋值.注意,需要单独处理int,float类型的属性.因为在xml配置中这些属性都是以字符串的形式来配置的,因此需要额外处理.
  • 5.如果属性property标签有ref属性,说明某个属性的值是一个对象,那么根据id(ref属性的值)去获取ref对应的对象,再给属性赋值.
  • 6.返回建立的对象,如果没有对应的id,或者下没有子标签都会返回null

demo

maven

    <dependencies>
        <dependency>
            <groupId>dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>1.6.1</version>
        </dependency>

    </dependencies>

applicationContext.xml

<beans>
	<bean id="user1" class="cn.qbz.thread.day1120.User">
		<property name="name" value="xiaoMing"></property>
		<property name="age" value="6"></property>
	</bean>
	<bean id="user2" class="cn.qbz.thread.day1120.User">
		<property name="name" value="laoWang"></property>
		<property name="age" value="99"></property>
	</bean>
</beans>
package cn.qbz.thread.day1120;

public class User {
    private String name;
    private String age;

    public String getName() {
        return name;
    }

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

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }
}
package cn.qbz.thread.day1120;

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

import java.lang.reflect.Field;
import java.util.List;

public class ClassPathXmlApplicationContext {
    private String xpath;

    public ClassPathXmlApplicationContext(String xpath) {
        this.xpath = xpath;
    }

    public Object getBean(String beanId) throws Exception {
        if (isEmpty(beanId)) {
            throw new Exception("bean Id is null !");
        }

        SAXReader saxReader = new SAXReader();
        Document document = saxReader.read(this.getClass().getClassLoader().getResource(xpath));

        //获取到根节点
        Element rootElement = document.getRootElement();
        //获取到根节点下的所有的子节点
        List<Element> elements = rootElement.elements();

        for (Element element : elements) {
            //获取到节点上的属性
            String id = element.attributeValue("id");
            if (isEmpty(id)) {
                continue;
            }
            if (!id.equals(beanId)) {
                continue;
            }
            // 使用java反射机制初始化对象
            String beanClass = element.attributeValue("class");
            Class<?> forName = Class.forName(beanClass);
            Object newInstance = forName.newInstance();
            List<Element> propertyElementList = element.elements();
            for (Element el : propertyElementList) {
                String name = el.attributeValue("name");
                String value = el.attributeValue("value");
                Field declaredField = forName.getDeclaredField(name);
                declaredField.setAccessible(true);
                declaredField.set(newInstance, value);
            }
            return newInstance;
        }
        return null;
    }

    public Boolean isEmpty(String str) {
        return (str == null || "".equals(str.trim()));
    }
}
package cn.qbz.thread.day1120;

public class SpringIOCTest {
    public static void main(String[] args) throws Exception {
        ClassPathXmlApplicationContext classPath = new ClassPathXmlApplicationContext("applicationContext.xml");
        User user = (User) classPath.getBean("user2");
        System.out.println(user.getName() + "---" + user.getAge());
    }
}

注意: this.getClass().getClassLoader().getResourceAsStream(xmlPath) 获取当前项目路径xmlPath

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏爱撒谎的男孩

Struts2之类型转换器

3625
来自专栏Android机动车

转向Kotlin——枚举类和扩展

Kotlin中的枚举类和Java中的枚举类型非常相似,具有类的特性。一般将可枚举的同类型的一组值作为枚举类定义。

912
来自专栏阿杜的世界

【译】11条Java异常处理的最佳实践

在之前关于Java异常的文章中,已经探讨过suppressed exceptions和Java Exceptions Tutorial 两个方面的内容。要想在...

884
来自专栏编程微刊

用原型链的方式写一个类和子类

1462
来自专栏木木玲

Reference 、ReferenceQueue 详解

3267
来自专栏老马说编程

(86) 动态代理 / 计算机程序的思维逻辑

前面两节,我们介绍了反射和注解,利用它们,可以编写通用灵活的程序,本节,我们来探讨Java中另外一个动态特性 - 动态代理。 动态代理是一种强大的功能,它可以...

1946
来自专栏www.96php.cn

PHP关键字、PHP 语言结构(Language constructs)和函数的区别

1、 什么是语言结构和函数 语言结构: 就是PHP语言的关键词,语言语法的一部分; 它不可以被用户定义或者添加到语言扩展或者库中; ...

3949
来自专栏Golang语言社区

厚土Go学习笔记 | 12. if 语句

在 for 循环的最后一个代码演示中,有了 if 语句。 那个 if 语句是这样写的 if (i>3) { break } 有一点,你要知道。在Go语言...

35513
来自专栏Android机动车

转向Kotlin——数据类和封闭类

数据类是Kotlin的一个语法糖。Kotlin编译器会自动为数据类生成一些成员函数,以提高开发效率。

872
来自专栏闪电gogogo的专栏

Python初学基础

初入坑Python,打算跟着沫凡小哥的学习视频打个基础,此篇文章做一些简单的学习记录,加油加油加油啦 沫凡小哥的学习网站:https://morvanzhou....

4017

扫码关注云+社区

领取腾讯云代金券