一、引言
本文以BeanFactory为切入点,浅谈Spring是如何创建Bean的。
二、何为BeanFactory
当谈到Spring时,我们首先联想到的是IOC、AOP两大特性,这种高逼格的东西,让一些java初学者望而却步,但其实它本质上就是个"Bean容器"。而容器中的Bean对象就是由BeanFactory生产的,BeanFactory通过工厂模式实现对Bean对象的管理从而隐藏了对象的具体实现细节。下面我们看看BeanFactory是如何创建Bean的
三、实例化Bean对象
Bean在实例化之前,必须是在Bean容器启动之后。所以我们分两个阶段介绍:
- Bean容器的启动阶段;
- Bean对象实例化阶段;
启动阶段
- 首先SpringBoot会读取Bean的xml配置文件,或者扫描相关注解,转换成一个BeanDefinition对象,其中保存了该bean的各种信息:
beanClass
: bean的class属性scope
:bean是否单例abstractFlag
: 该bean是否抽象lazyInit
: 是否延迟初始化autowireMode
:保存是否自动装配dependencyCheck
:保存是否坚持依赖dependsOn
:保存该bean依赖于哪些bean(这些bean必须在初始化时提前初始化)constructorArgumentValues
:保存通过构造函数注入的依赖propertyValues
:保存通过setter方法注入的依赖factoryBeanName
和factoryMethodName
:用于factorybean,即工厂类型的beaninitMethodName
和destroyMethodName
:分别对应bean的init-method和destroy-method属性
- 然后通过
BeanDefinitionRegistry
将这些bean注册到BeanFactory中:
java
public interface BeanDefinitionRegistry extends AliasRegistry {
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)throws BeanDefinitionStoreException;
void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
boolean containsBeanDefinition(String beanName);
String[] getBeanDefinitionNames();
int getBeanDefinitionCount();
boolean isBeanNameInUse(String beanName);
}
BeanFactory的实现类,需要实现BeanDefinitionRegistry 接口:
java
@SuppressWarnings("serial")
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
/** Map of bean definition objects, keyed by bean name */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
// ... ... this.beanDefinitionMap.put(beanName, beanDefinition);
// ... ...
}
在这里BeanDefinition
被注册到了 DefaultListableBeanFactory
, 保存在它的一个ConcurrentHashMap中。
实例化阶段
实例化阶段主要是通过反射或者CGLIB对bean进行实例化,在这个阶段Spring又给我们暴露了很多的扩展点:
- 各种的Aware接口,比如
BeanFactoryAware
,MessageSourceAware
,ApplicationContextAware
。 BeanPostProcessor
接口: 实现了BeanPostProcessor
接口的bean,在实例化bean时Spring会帮我们调用接口中的方法:- 在 Bean 初始化前后进行额外处理:通过重写
BeanPostProcessor
接口的方法,可以在目标 Bean 的初始化方法(eg:InitializingBean
的afterPropertiesSet
)调用之前(postProcessBeforeInitialization
)和之后(postProcessAfterInitialization
)执行自定义的处理操作。
- 在 Bean 初始化前后进行额外处理:通过重写
InitializingBean
接口:实现了InitializingBean
接口的bean,在实例化bean时Spring会帮我们调用afterPropertiesSet
方法。DisposableBean
接口:实现了BeanPostProcessor
接口的bean,在该bean死亡时Spring会帮我们调用destroy
方法。
补充:注解@PostConstruct
和 @PreDestroy
也能达到 InitializingBean
接口 和 DisposableBean
接口的效果。
四. 总结
spring容器接管了bean的实例化,不仅仅是通过依赖注入达到了松耦合的效果,同时给我们提供了各种的扩展接口,来在bean的生命周期的各个时期插入我们自己的代码:
0) BeanFactoryPostProcessor接口(在容器启动阶段)
1) 各种的Aware接口
2) BeanPostProcessor接口
3) InitializingBean接口(@PostConstruct, init-method)
4) DisposableBean接口(@PreDestroy, destory-method)