使用java反射机制和dom4j写一个简版spring-ioc

1.新建一个springboot项目

	<groupId>com.springioc</groupId>
    <artifactId>spring-ioc</artifactId>
    <version>1.0-SNAPSHOT</version>

2.在pom文件中引入

		<dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.10</version>
        </dependency>

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

3.创建一个User对象

package com.entity;

public class User {

    private String id;

    private String name;

    public String getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

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

4.在resource文件中创建一个application.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.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">

	<bean id = "user1" class="com.entity.User">
		<property name="id" value="10"/>
		<property name="name" value="牛牛"/>
	</bean>

	<bean id = "user2" class="com.entity.User">
		<property name="id" value="10"/>
		<property name="name" value="方方"/>
	</bean>

</beans>

5.创建一个ClassPathXmlApplicationContext类实现装在bean并赋值返回一个bean实例

package com;

import com.entity.User;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.List;

/**
 * Created by vn0790t on 2020/5/15.
 */
public class ClassPathXmlApplicationContext {

    private String ID; ;
    private String CLASSA;
    private String NAME;
    private String VALUE;

    public ClassPathXmlApplicationContext(){
        init();
    }

    public void init(){
        ID = "id";
        CLASSA = "class";
        NAME = "name";
        VALUE = "value";
    }

    public Object getBean(String beanName) throws Exception {
        SAXReader reader = new SAXReader();
        //定位到resources目录
        URL resource = this.getClass().getClassLoader().getResource("application.xml");
        File file = new File(resource.getFile());
        //读取application.xml配置文件
        Document document = reader.read(file);

        //获取标签beans(一级标签)
        Element rootElement = document.getRootElement();
        //获取beans下的子标签bean(二级标签)
        List<Element> elements = rootElement.elements();
        for (Element element : elements){
            //获取bean标签中id属性的值
            String id = element.attributeValue(ID);
            //如果不是要找的beanName就结束本次循环,开始下次循环
            if(!id.equals(beanName)){
                continue;
            }

            //获取bean标签中的class属性的值
            String claessPath = element.attributeValue(CLASSA);
            Class<?> forName = Class.forName(claessPath);
            //使用无参构造函数创建bean对象
            Object newInstance = forName.newInstance();

            //获取bean下的子集标签property(三级标签)
             List<Element> eson = element.elements();
            for (Element e : eson){
                //获取属性名name的值
                String name = e.attributeValue(NAME);
                //获取属性名value的值
                String value = e.attributeValue(VALUE);
                //获取bean对象的属性
                Field field = forName.getDeclaredField(name);
                //设置权限(因为属性是私有化的,所以需要设置权限)
                field.setAccessible(true);
                //将bean对象的属性赋值
                field.set(newInstance,value);
            }

            return newInstance;
        }

        return null;
    }

    public static void main(String[] args) throws Exception {
        ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext();
        try {
            User user= (User)classPathXmlApplicationContext.getBean("user1");
            System.out.println(user);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

6.SpringIOC底层原理

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

详细步骤如下:

1.利用传入的参数获取xml文件的流,并且利用dom4j解析成Document对象
2.对于Document对象获取根元素对象<beans>后对下面的<bean>标签进行遍历,判断是否有符合的id.
3.如果找到对应的id,相当于找到了一个Element元素,开始创建对象,先获取class属性,根据属性值利用反射建立对象.
4.遍历<bean>标签下的property标签,并对属性赋值.注意,需要单独处理int,float类型的属性.因为在xml配置中这些属性都是以字符串的形式来配置的,因此需要额外处理.
5.如果属性property标签有ref属性,说明某个属性的值是一个对象,那么根据id(ref属性的值)去获取ref对应的对象,再给属性赋值.
6.返回建立的对象,如果没有对应的id,或者<beans>下没有子标签都会返回null
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring-IOCSpring框架的核心部分之一,它是一种设计模式,全称为Inversion of Control(控制反转)。它通过将对象的创建、依赖关系的管理和对象的生命周期交给Spring容器来实现,从而降低了组件之间的耦合度,提高了代码的可重用性和可维护性。Spring-IOC的实现主要依靠Spring容器,Spring容器是Spring框架的核心,它负责创建、管理和装配Bean对象,其中Bean是Spring框架中最基本的组件。 Spring-IOC的实现主要有两种方式:BeanFactory和ApplicationContext。其中,BeanFactory是Spring-IOC的基本实现,而ApplicationContext是BeanFactory的子接口,提供了更多高级特性。ApplicationContext是Spring框架中最常用的IOC容器,它除了提供BeanFactory的所有功能外,还提供了更多的企业级特性,例如AOP、事务管理、国际化、事件传播等。 下面是一个简单的Spring-IOC的例子,假设我们有一个UserService接口和一个UserServiceImpl实现类,我们可以通过Spring-IOC容器来创建和管理UserServiceImpl对象: 1.定义UserService接口和UserServiceImpl实现类 ```java public interface UserService { void addUser(User user); } @Service public class UserServiceImpl implements UserService { @Override public void addUser(User user) { // 添加用户的具体实现 } } ``` 2.在Spring配置文件中配置UserService实例 ```xml <bean id="userService" class="com.example.service.UserServiceImpl"/> ``` 3.在代码中获取UserService实例并使用 ```java ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserService userService = context.getBean("userService", UserService.class); User user = new User(); userService.addUser(user); ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值