Spring自己实现一个简单的 Spring IOC 自己实现简单的 Spring
Posted 九师兄
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring自己实现一个简单的 Spring IOC 自己实现简单的 Spring相关的知识,希望对你有一定的参考价值。
1.概述
你有自己实现过简单的 Spring 吗?
Spring 的 IOC 本质就是一个大工厂,我们想想一个工厂是怎么运行的呢?
生产产品
:一个工厂最核心的功能就是生产产品。在 Spring 里,不用 Bean 自己来实例化,而是交给 Spring,应该怎么实现呢?——答案毫无疑问,反射。
那么这个厂子的生产管理是怎么做的?你应该也知道——工厂模式。
库存产品
:工厂一般都是有库房的,用来库存产品,毕竟生产的产品不能立马就拉走。Spring 我们都知道是一个容器,这个容器里存的就是对象,不能每次来取对象,都得现场来反射创建对象,得把创建出的对象存起来。
订单处理
:还有最重要的一点,工厂根据什么来提供产品呢?订单。这些订单可能五花八门,有线上签签的、有到工厂签的、还有工厂销售上门签的……最后经过处理,指导工厂的出货。
在 Spring 里,也有这样的订单,它就是我们 bean 的定义和依赖关系,可以是 xml 形式,也可以是我们最熟悉的注解形式。
我们简单地实现一个 mini 版的 Spring IOC:
Bean 定义:
Bean 通过一个配置文件定义,把它解析成一个类型。
beans.properties
偷懒,这里直接用了最方便解析的 properties,这里直接用一个<key,value>
类型的配置来代表 Bean 的定义,其中 key 是 beanName,value 是 class
userDao:cn.fighter3.bean.UserDao
BeanDefinition.java
bean 定义类,配置文件中 bean 定义对应的实体
public class BeanDefinition
private String beanName;
private Class beanClass;
//省略getter、setter
ResourceLoader.java
资源加载器,用来完成配置文件中配置的加载
public class ResourceLoader
public static Map<String, BeanDefinition> getResource()
Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>(16);
Properties properties = new Properties();
try
InputStream inputStream = ResourceLoader.class.getResourceAsStream("/beans.properties");
properties.load(inputStream);
Iterator<String> it = properties.stringPropertyNames().iterator();
while (it.hasNext())
String key = it.next();
String className = properties.getProperty(key);
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setBeanName(key);
Class clazz = Class.forName(className);
beanDefinition.setBeanClass(clazz);
beanDefinitionMap.put(key, beanDefinition);
inputStream.close();
catch (IOException | ClassNotFoundException e)
e.printStackTrace();
return beanDefinitionMap;
BeanRegister.java
对象注册器,这里用于单例 bean 的缓存,我们大幅简化,默认所有 bean 都是单例的。可以看到所谓单例注册,也很简单,不过是往 HashMap 里存对象。
public class BeanRegister
//单例Bean缓存
private Map<String, Object> singletonMap = new HashMap<>(32);
/**
* 获取单例Bean
*
* @param beanName bean名称
* @return
*/
public Object getSingletonBean(String beanName)
return singletonMap.get(beanName);
/**
* 注册单例bean
*
* @param beanName
* @param bean
*/
public void registerSingletonBean(String beanName, Object bean)
if (singletonMap.containsKey(beanName))
return;
singletonMap.put(beanName, bean);
BeanFactory.java
对象工厂,我们最核心的一个类,在它初始化的时候,创建了 bean 注册器,完成了资源的加载。
获取 bean 的时候,先从单例缓存中取,如果没有取到,就创建并注册一个 bean
public class BeanFactory
private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
private BeanRegister beanRegister;
public BeanFactory()
//创建bean注册器
beanRegister = new BeanRegister();
//加载资源
this.beanDefinitionMap = new ResourceLoader().getResource();
/**
* 获取bean
*
* @param beanName bean名称
* @return
*/
public Object getBean(String beanName)
//从bean缓存中取
Object bean = beanRegister.getSingletonBean(beanName);
if (bean != null)
return bean;
//根据bean定义,创建bean
return createBean(beanDefinitionMap.get(beanName));
/**
* 创建Bean
*
* @param beanDefinition bean定义
* @return
*/
private Object createBean(BeanDefinition beanDefinition)
try
Object bean = beanDefinition.getBeanClass().newInstance();
//缓存bean
beanRegister.registerSingletonBean(beanDefinition.getBeanName(), bean);
return bean;
catch (InstantiationException | IllegalAccessException e)
e.printStackTrace();
return null;
2.测试
UserDao.java
我们的 Bean 类,很简单
public class UserDao
public void queryUserInfo()
System.out.println("A good man.");
单元测试
public class ApiTest
@Test
public void test_BeanFactory()
//1.创建bean工厂(同时完成了加载资源、创建注册单例bean注册器的操作)
BeanFactory beanFactory = new BeanFactory();
//2.第一次获取bean(通过反射创建bean,缓存bean)
UserDao userDao1 = (UserDao) beanFactory.getBean("userDao");
userDao1.queryUserInfo();
//3.第二次获取bean(从缓存中获取bean)
UserDao userDao2 = (UserDao) beanFactory.getBean("userDao");
userDao2.queryUserInfo();
运行结果
A good man.
A good man.
至此,我们一个乞丐+破船版的 Spring 就完成了,代码也比较完整,有条件的可以跑一下。
M.参考
以上是关于Spring自己实现一个简单的 Spring IOC 自己实现简单的 Spring的主要内容,如果未能解决你的问题,请参考以下文章
javaSpring 自己模拟 Spring 实现 IOC依赖注入 并且 解决 循环依赖