极简IOC

Meteor 2023-09-21 17:53:17
Categories: Tags:

简介

IOC 控制反转,一种设计思想,即由我们设计对象的创建过程中所需要的一切,如对象的字段、方法,然后由容器控制对象的真实创建(容器可以简单的理解为一个创建和存储对象的工厂)

IOC提供的功能就是将我们对一个对象的设计存储到容器中,然后在代码中通过容器提供的方式获取到容器创建的实例对象。

使用IOC的过程大致可分为:设计对象、将设计注册进容器、通过容器获取对象、使用对象四个阶段

接下来实现一个最简单的对象容器,建议先把文章阅读一遍,再根据文末的目录结构和依赖对照文章实现一遍

Bean:被Spring容器管理的对象
源码:small-spring01

设计对象

在 Spring 中把我们对一个对象的设计存储到 BeanDefinition 类中包括对象的类型、字段、方法等等,本篇目的在于创建一个极简IOC,因此下面创建一个很简单的 BeanDefinition

BeanDefinition

package com.meteor;

public class BeanDefinition {
private final Object bean;

public BeanDefinition(Object bean) {
this.bean = bean;
}

public Object getBean() {
return bean;
}
}

这个 BeanDefinition 直接存储了实例对象,之后会逐渐修改其实现,慢慢接近真实的 BeanDefinition

创建容器

这里我们使用一个Map作为容器,key是对象名,value是 BeanDefinition

BeanFactory

package com.meteor;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class BeanFactory {
private Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();

public Object getBean(String name) {
return beanDefinitionMap.get(name).getBean();
}

public void registerBeanDefinition(String name, BeanDefinition beanDefinition) {
beanDefinitionMap.put(name, beanDefinition);
}
}

容器提供了两个最基本的方法,将 BeanDefinition 注册到容器中以及获取实例对象

测试

用一个测试类将流程走一遍,测试之前先提供一个 Bean,这个类是我们要交给容器管理的,在我们需要的时候直接从容器中获取

UserService

package com.meteor.bean;

public class UserService {
public void queryUserInfo() {
System.out.println("查询用户信息");
}
}

开始测试

package com.meteor;

import com.meteor.bean.UserService;
import org.junit.Test;

public class MainTest {
@Test
public void test_BeanFactory(){
//初始化 BeanFaactory
BeanFactory beanFactory = new BeanFactory();

//将创建好的Bean即 UserService 放入到 BeanDefinition 中
BeanDefinition beanDefinition = new BeanDefinition(new UserService());

//将 BeanDefinition 注册到 BeanFactory 中
beanFactory.registerBeanDefinition("userService", beanDefinition);

//从 BeanFactory 中获取 Bean
UserService userService = (UserService) beanFactory.getBean("userService");
userService.queryUserInfo();
}
}

输出结果

查询用户信息

Process finished with exit code 0

总结

目前已经将IOC的流程走了一遍,首先,我们有一个对象需要交给容器管理,即 UserService,其次,要有一个类存储 UserService 的设计,即 BeanDefinition ,然后,要有一个容器,即 BeanFactory,需要将 BeanDefinition 注册到 BeanFactory 中,最后就可以从 BeanFactory 中直接获取到 UserService,因为在获取的过程中,BeanFactory 会根据BeanDefinition创建Bean。

其实 BeanDefinition 中存在的应该是 Bean 的Class对象,之后就可以利用反射或cglib的字节码生成创建实例对象,本篇简化了这一操作,直接将Bean的实例对象存储在 BeanDefinition,下一篇解决这个问题。

目录结构

src
├── main
│ └── java
│ └── com.meteor
│ ├── BeanDefinition.java
│ └── BeanFactory.java
└── test
└── java
└── com.meteor
├── bean
│ └── UserService.java
└── MainTest.java

依赖

<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>RELEASE</version>
<scope>test</scope>
</dependency>
</dependencies>