极简IOC
简介
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(){ BeanFactory beanFactory = new BeanFactory();
BeanDefinition beanDefinition = new BeanDefinition(new UserService());
beanFactory.registerBeanDefinition("userService", beanDefinition);
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>
|