前言:
最近在学习 github上的项目mini-spring
github地址:mini-spring
很适合了解学习Spring框架原理的项目,感兴趣的可以给作者点点STAR
项目简介:
mini-spring是简化版的spring框架,能帮助你快速熟悉spring源码和掌握spring的核心原理。抽取了spring的核心逻辑,代码极度简化,保留spring的核心功能,如IoC和AOP、资源加载器、事件监听器、类型转换、容器扩展点、bean生命周期和作用域、应用上下文等核心功能。
作者的文档虽然没写那么多的解释,但是没有废话全是干货,搭配源码食用更佳。
mini-spring重点看懂第二个分支上的内容,也就是bean的注册和获取。后续都是基于这样的结构,所有在这个分支上花费的时间比较多,主要是搞懂调用继承关系,这样在扩展相关功能的时候都知道从何入手。
具体实现
1. 定义BeanDefinition
顾名思义,用于定义bean信息的类,包含bean的class类型、构造参数、属性值等信息,每个bean对应一个BeanDefinition的实例。简化BeanDefinition仅包含bean的class类型。
/**
* BeanDefinition实例保存bean的信息,包括class类型、方法构造参数、是否为单例等,此处简化只包含class类型
*
*/
public class BeanDefinition {
private Class beanClass;
public BeanDefinition(Class beanClass) {
this.beanClass = beanClass;
}
public Class getBeanClass() {
return beanClass;
}
public void setBeanClass(Class beanClass) {
this.beanClass = beanClass;
}
}
2.定义BeanDefinitionRegistry接口
BeanDefinition注册表接口,定义注册BeanDefinition的方法。
/**
* BeanDefinition注册表接口
*/
public interface BeanDefinitionRegistry {
/**
* 向注册表中注BeanDefinition
*
* @param beanName
* @param beanDefinition
*/
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition);
}
3.定义Bean容器 BeanFactory
/**
* bean容器
*/
public interface BeanFactory {
/**
* 获取bean
*
* @param name
* @return
* @throws BeansException bean不存在时
*/
Object getBean(String name) throws BeansException;
}
4.定义SingletonBeanRegistry单例注册表
注册好对象后,放入单例注册表中,
5.定义实现Bean容器的抽象类AbstractBeanFactory。
这个抽象类中实现了getBean方法,并且提供了两个抽象方法,createBean()和getBeanDefinition().
所有在获取Bean的时候的步骤为:
1、先从单例注册表中获取Bean
2、获取不到的话,就通过获取BeanDefinition的方式获取BeanDefinition
3、获取到BeanDefinition后,再通过BeanDefinition去创建Bean,然后存入单例注册表中
public abstract class AbstractBeanFactory extends DefaultSingletonBeanRegistry implements BeanFactory {
@Override
public Object getBean(String name) throws BeansException {
//先从单例注册表中获取
Object bean = getSingleton(name);
if (bean != null) {
return bean;
}
//获取不到的话,就通过获取BeanDefinition的方式获取BeanDefinition(注册的时候存入的BeanDefinition)
BeanDefinition beanDefinition = getBeanDefinition(name);
//获取到BeanDefinition后,再通过BeanDefinition去创建Bean,然后存入单例注册表中
return createBean(name, beanDefinition);
}
protected abstract Object createBean(String beanName, BeanDefinition beanDefinition) throws BeansException;
protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeansException;
}
6.定义AbstractBeanFactory 的子类AbstractAutowireCapableBeanFactory
重写createBean(),创建Bean然后注册。
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory {
@Override
protected Object createBean(String beanName, BeanDefinition beanDefinition) throws BeansException {
return doCreateBean(beanName, beanDefinition);
}
//通过反射的方式创建Bean
protected Object doCreateBean(String beanName, BeanDefinition beanDefinition) {
Class beanClass = beanDefinition.getBeanClass();
Object bean = null;
try {
bean = beanClass.newInstance();
} catch (Exception e) {
throw new BeansException("Instantiation of bean failed", e);
}
addSingleton(beanName, bean);
return bean;
}
}
7.定义DefaultListableBeanFactory,我们真正调用的Bean容器。
Bean容器实现了BeanDefinitionRegistry,并且继承了AbstractAutowireCapableBeanFactory,所以同时具有了注册Bean和获取Bean的能力。
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements BeanDefinitionRegistry {
private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
beanDefinitionMap.put(beanName, beanDefinition);
}
@Override
protected BeanDefinition getBeanDefinition(String beanName) throws BeansException {
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if (beanDefinition == null) {
throw new BeansException("No bean named '" + beanName + "' is defined");
}
return beanDefinition;
}
}
8.进行测试:
public class BeanDefinitionAndBeanDefinitionRegistryTest {
@Test
public void testBeanFactory() throws Exception {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
BeanDefinition beanDefinition = new BeanDefinition(HelloService.class);
//注册Bean信息
beanFactory.registerBeanDefinition("helloService", beanDefinition);
//获取Bean。
HelloService helloService = (HelloService) beanFactory.getBean("helloService");
helloService.sayHello();
}
}
public class HelloService {
public String sayHello() {
System.out.println("hello");
return "hello";
}
}
测试结果:
9.调用关系(重要)
下面来看一下具体的调用关系,这张图非常重要,很直观有助于我们一眼看清楚整体的设计。
10.要点分析:
AbstractBeanFactory
-
AbstractBeanFactory是DefaultSingletonBeanRegistry单例注册表的子类,具有从单例注册表中获取Bean,存储Bean的能力。
-
AbstractBeanFactory实现了BeanFactory的getBean()接口,而这个getBean()方法通过自身的两个抽象方法去实现,一个是getBeanDefinition()一个是createBean()。
- getBeanDefinition() :获取BeanDefinition信息。放在我们真正调用的Bean容器DefaultListableBeanFactory中去实现(就是从注册的时候放进去的map中去取BeanDifiniton信息。)
- createBean(): 获取到BeanDefinition信息后,通过BeanDefinition去创建Bean并存入单例注册表,放在抽象子类AbstractAutowireCapableBeanFactory中去实现。
- 这两个方法一个放在Bean容器中实现,一个放在抽象子类中实现,分析这样设计的原因:createBean()方法是已经获取到了具体的BeanDefinition信息,直接通过反射的方式去创建Bean就可以了,所以放在抽象子类中当做默认的实现。
DefaultListableBeanFactory
DefaultListableBeanFactory作为bean容器,实现了BeanDefinitionRegistry,并且继承了AbstractAutowireCapableBeanFactory,所以同时具有了注册Bean和获取Bean的能力。
总结:
通过对mini-spring的bean-definition-and-bean-definition-registry分支代码分析,学习了如何自己实现Spring注册和获取Bean。但是项目中在实例化Bean的时候,通过beanClass.newInstance()来实例化,仅适用于bean有无参构造函数的情况。在下面的篇章中,我们继续学习mini-spring,学习其他实例化Bean的方式。