我们将分为几步来编写简易 IOC,首先设计组件,再设计接口,然后关注实现。
1. 设计组件。
我们还记得Spring中最重要的有哪些组件吗?BeanFactory 容器,BeanDefinition Bean的基本数据结构,当然还需要加载Bean的资源加载器。大概最后最重要的就是这几个组件。
容器用来存放初始化好的Bean,BeanDefinition 就是Bean的基本数据结构,比如Bean的名称,Bean的属性 PropertyValue,Bean的方法,是否延迟加载,依赖关系等。资源加载器就简单了,就是一个读取
2. 设计接口
首先肯定需要一个BeanFactory,就是Bean容器,容器接口至少有2个最简单的方法,一个是获取Bean,一个注册Bean.
/** * 需要一个beanFactory 定义ioc 容器的一些行为 比如根据名称获取bean, 比如注册bean,参数为bean的名称,bean的定义 * * @author stateis0 * @version 1.0.0 * @Date 2017/11/30 */public interface BeanFactory { /** * 根据bean的名称从容器中获取bean对象 * * @param name bean 名称 * @return bean实例 * @throws Exception 异常 */ Object getBean(String name) throws Exception; /** * 将bean注册到容器中 * * @param name bean 名称 * @param bean bean实例 * @throws Exception 异常 */ void registerBeanDefinition(String name, BeanDefinition bean) throws Exception;}
根据Bean的名字获取Bean对象,注册参数有2个,一个是Bean的名字,一个是 BeanDefinition 对象。
定义完了Bean最基本的容器,还需要一个最简单 BeanDefinition 接口,我们为了方便,但因为我们这个不必考虑扩展,因此可以直接设计为类,BeanDefinition 需要哪些元素和方法呢?
需要一个 Bean 对象,一个Class对象,一个ClassName字符串,还需要一个元素集合 PropertyValues。这些就能组成一个最基本的 BeanDefinition 类了。那么需要哪些方法呢?其实就是这些属性的get set 方法。
我们看看该类的详细:
package cn.thinkinjava.myspring;/*** bean 的定义** @author stateis0*/public class BeanDefinition { /** * bean */ private Object bean; /** * bean 的 CLass 对象 */ private Class beanClass; /** * bean 的类全限定名称 */ private String ClassName; /** * 类的属性集合 */ private PropertyValues propertyValues = new PropertyValues(); /** * 获取bean对象 */ public Object getBean() { return this.bean; } /** * 设置bean的对象 */ public void setBean(Object bean) { this.bean = bean; } /** * 获取bean的Class对象 */ public Class getBeanclass() { return this.beanClass; } /** * 通过设置类名称反射生成Class对象 */ public void setClassname(String name) { this.ClassName = name; try { this.beanClass = Class.forName(name); } catch (ClassNotFoundException e) { e.printStackTrace(); } } /** * 获取bean的属性集合 */ public PropertyValues getPropertyValues() { return this.propertyValues; } /** * 设置bean的属性 */ public void setPropertyValues(PropertyValues pv) { this.propertyValues = pv; }}
有了基本的 BeanDefinition 数据结构,还需要一个从
package cn.thinkinjava.myspring;import cn.thinkinjava.myspring.io.ResourceLoader;import java.util.HashMap;import java.util.Map;/** * 抽象的bean定义读取类 * * @author stateis0 */public abstract class AbstractBeanDefinitionReader implements BeanDefinitionReader { /** * 注册bean容器 */ private Map registry; /** * 资源加载器 */ private ResourceLoader resourceLoader; /** * 构造器器必须有一个资源加载器, 默认插件创建一个map容器 * * @param resourceLoader 资源加载器 */ protected AbstractBeanDefinitionReader(ResourceLoader resourceLoader) { this.registry = new HashMap<>(); this.resourceLoader = resourceLoader; } /** * 获取容器 */ public Map getRegistry() { return registry; } /** * 获取资源加载器 */ public ResourceLoader getResourceLoader() { return resourceLoader; } }
有了这几个抽象类和接口,我们基本能形成一个雏形,BeanDefinitionReader 用于从
3. 如何实现
刚刚我们说了具体的流程:从