目录
IoC容器系列的设计与实现:BeanFactory和ApplicationContext
IOC容器接口设计图
其中,BeanFactory 定义了基本的 IoC 容器的规范。
BeanFactory 容器设计原理
以 DefaultListableBeanFactory 的实现为例,来说明简单 IoC 容器的设计原理:
-
BeanFactory实现是IoC容器的基本形式,各种ApplicationContext的实现是IoC容器的高级表现形式
-
DefaultListableBeanFactory 作为一个默认的功能完整的IoC容器来使用
-
Resource是Spring用来封装I/O操作的类
编程式使用IOC容器
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(new ClassPathResource("UserBean.xml"));
UserService userService = factory.getBean("userService", UserService.class);
ApplicationContext
ApplicationContext 是一个高级形态意义的 IoC 容器:
-
支持不同的信息源:继承接口Messagesource
-
访问资源:继承接口ResourceLoader
-
支持应用事件
-
在ApplicationContext中提供附加功能
设计原理
以 FileSystemXmlApplicationContext 为例,来说明 ApplicationContext 的设计原理:
其中,ApplicationContext 的主要功能在基类 AbstractRefreshableApplicationContext 中已经实现了。
上面的类图可以看出,ConfigurableApplicationContext 的父接口 ApplicationContext:
-
继承了 ListableBeanFactory 用于提供访问应用组件的方法
-
继承了 ResourceLoader 用于提供加载资源文件的方法
-
继承了 ApplicationEventPublisher 用于提供发布事件与注册监听器的方法
-
继承了 MessageSource 提供国际化的支持
AbstractRefreshableApplicationContext
IoC 容器的初始化
IoC 容器的初始化过程,主要就体现在 AbstractApplicationContext 的 refresh() 方法中,其实现如下:
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
...
@Override
public void refresh() throws BeansException, IllegalStateException {
this.startupShutdownLock.lock();
try {
this.startupShutdownThread = Thread.currentThread();
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// 1.Prepare this context for refreshing.
prepareRefresh();
// 2.Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 3.Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// 4.Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// 5.Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
//6.Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
// 7.Initialize message source for this context.
initMessageSource();
// 8.Initialize event multicaster for this context.
initApplicationEventMulticaster();
// 9.Initialize other special beans in specific context subclasses.
onRefresh();
// 10.Check for listener beans and register them.
registerListeners();
// 11.Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// 12.Last step: publish corresponding event.
finishRefresh();
}
catch (RuntimeException | Error ex ) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
contextRefresh.end();
}
}
finally {
this.startupShutdownThread = null;
this.startupShutdownLock.unlock();
}
}
...
}
各个方法功能说明如下:
创建 Bean 容器前的准备工作
prepareRefresh()
:准备工作,记录下容器的启动时间、标记“已启动”状态、处理配置文件中的占位符。
protected void prepareRefresh() {
// 记录启动时间
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
if (logger.isDebugEnabled()) {
if (logger.isTraceEnabled()) {
logger.trace("Refreshing " + this);
}
else {
logger.debug("Refreshing " + getDisplayName());
}
}
// Initialize any placeholder property sources in the context environment.
initPropertySources();
// 校验 XML 配置文件
getEnvironment().validateRequiredProperties();
// Store pre-refresh ApplicationListeners...
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
else {
// Reset local application listeners to pre-refresh state.
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
this.earlyApplicationEvents = new LinkedHashSet<>();
}
创建 Bean 容器,加载并注册 Bean
obtainFreshBeanFactory()
:这个方法是全文最重要的部分之一,这里将会初始化 BeanFactory、加载 Bean、注册 Bean 等等。
BeanDefinition 就是我们所说的 Spring 的 Bean,我们定义的各个 Bean 其实会转换成一个个 BeanDefinition 存在于 Spring 的 BeanFactory 中。Bean 在代码层面上可以简单认为是 BeanDefinition 的实例。
BeanDefinition 中保存了我们的 Bean 信息,比如这个 Bean 指向的是哪个类、是否是单例的、是否懒加载、这个 Bean 依赖了哪些 Bean 等等。
这一步会把配置文件就会解析成一个个的 Bean 定义,注册到 BeanFactory 中
// AbstractApplicationContext.java
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
return getBeanFactory(); // 返回刚刚创建的 BeanFactory
}
它会调用子类 AbstractRefreshableApplicationContext 的 refreshBeanFactory() 方法实现来刷新内部的 BeanFactory。
刷新 BeanFactory
其中,载入 Bean 定义信息的具体过程如下:
public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {
...
@Override
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) { // 如果 ApplicationContext 中已经加载过 BeanFactory 了,它会先销毁所有 Bean,并关闭 BeanFactory
destroyBeans();
closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = createBeanFactory(); // 初始化一个 DefaultListableBeanFactory
beanFactory.setSerializationId(getId()); // 用于 BeanFactory 的序列化
customizeBeanFactory(beanFactory); // 设置 BeanFactory 的两个配置属性:是否允许 Bean 覆盖、是否允许循环引用
loadBeanDefinitions(beanFactory); // 加载 Bean 到 BeanFactory 中
this.beanFactory = beanFactory;
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
...
}
ApplicationContext 虽然继承自 BeanFactory,但是它不应该被理解为 BeanFactory 的实现类,而是其内部持有一个实例化的 BeanFactory,即 DefaultListableBeanFactory ,后续所有的 BeanFactory 相关的操作其实是委托给这个实例来处理的。
上述代码中,最开始会创建一个 DefaultListableBeanFactory,并保存在 ApplicationContext 中,这一步的主要的方法是:loadBeanDefinitions()。
加载 Bean
loadBeanDefinitions()
:这个方法将根据配置,加载各个 Bean,然后放到 BeanFactory 中
其中,loadBeanDefinitions() 的实现如下:
public abstract class AbstractXmlApplicationContext extends AbstractRefreshableConfigApplicationContext {
...
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// Configure the bean definition reader with this context's
// resource loading environment.
beanDefinitionReader.setEnvironment(getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the bean definitions.
initBeanDefinitionReader(beanDefinitionReader);
loadBeanDefinitions(beanDefinitionReader);
}
...
}
注册 BeanDefinition
// org/springframework/beans/factory/support/DefaultListableBeanFactory.java
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
}
}
到这里已经初始化了 Bean 容器,
Bean 容器实例化完成后
准备 Bean 容器
prepareBeanFactory(beanFactory)
:在使用 ApplicationContext 时需要做一些准备工作。这些准备工作是在这一步处理的,包括:为容器配置 ClassLoader、PropertyEditor 和 BeanPost-Processor 等,从而为容器的启动做好必要的准备。
postProcessBeanFactory(beanFactory)
postProcessBeanFactory(beanFactory) 是在所有的 beanDenifition 加载完成之后,bean 实例化之前执行。
为了能够修改 bean definitions,或者对 BeanFactory 做一些其他配置,就可以通过继承 ClassPathXmlApplicationContext 类,并重写 postProcessBeanFactory 方法即可。
invokeBeanFactoryPostProcessors(beanFactory)
拿到当前应用上下文 beanFactoryPostProcessors 变量中的值,实例化并调用所有已注册的 BeanFactoryPostProcessor。必须在singleton之前调用。
registerBeanPostProcessors(beanFactory);
初始化所有的 singleton beans。实例化并且注册所有的BeanPostProcessor beans,必须在任何bean实例化之前调用。
初始化所有的 singleton beans
finishBeanFactoryInitialization(beanFactory)
:会负责初始化所有的 singleton beans。
到目前为止,应该说 BeanFactory 已经创建完成,并且所有的实现了 BeanFactoryPostProcessor 接口的 Bean 都已经初始化并且其中的 postProcessBeanFactory(factory) 方法已经得到回调执行了。而且 Spring 已经“手动”注册了一些特殊的 Bean,如 environment、systemProperties 等。
剩下的就是初始化 singleton beans 了,我们知道它们是单例的,如果没有设置懒加载,那么 Spring 会在接下来初始化所有的 singleton beans。
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// Register a default embedded value resolver if no BeanFactoryPostProcessor
// (such as a PropertySourcesPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null);
// Allow for caching all bean definition metadata, not expecting further changes.
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons(); // 开始初始化
}
其中,preInstantiateSingletons() 的实现如下:
// org/springframework/beans/factory/support/DefaultListableBeanFactory.java
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
}
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof SmartFactoryBean<?> smartFactoryBean && smartFactoryBean.isEagerInit()) {
getBean(beanName);
}
}
else {
getBean(beanName); // 对于普通的 Bean,只要调用 getBean(beanName) 这个方法就可以进行初始化了
}
}
}
// Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton smartSingleton) {
StartupStep smartInitialize = getApplicationStartup().start("spring.beans.smart-initialize")
.tag("beanName", beanName);
smartSingleton.afterSingletonsInstantiated();
smartInitialize.end();
}
}
}
其中,getBean 的实现如下:
// org/springframework/beans/factory/support/AbstractBeanFactory.java
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
// ...
return createBean(beanName, mbd, args);
// ...
}
创建 Bean
doCreateBean()
:创建 Bean 实例
// org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// ...
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
// ...
}
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// ...
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args); // 创建 Bean 实例
}
// ...
// 依赖注入:属性注入
populateBean(beanName, mbd, instanceWrapper);
// 调用bean factory的回调,执行bean初始化的后处理流程
exposedObject = initializeBean(beanName, exposedObject, mbd);
// ...
// 处理循环依赖
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
// ...
}
}
}
}
}
创建 Bean 实例的过程
// org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// Make sure bean class is actually resolved at this point.
Class<?> beanClass = resolveBeanClass(mbd, beanName);
// ...
if (resolved) {
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null, null); // 构造函数依赖注入
}
else {
return instantiateBean(beanName, mbd); // 无参构造函数依赖注入
}
}
// Candidate constructors for autowiring?
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
// Preferred constructors for default construction?
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}
// No special handling: simply use no-arg constructor.
return instantiateBean(beanName, mbd); // 无参构造函数依赖注入
}
这里,我们以无参构造函数的依赖注入为例来介绍其注入过程,其代码实现下:
// org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java
protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
try {
Object beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this); // 实例化
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
initBeanWrapper(bw);
return bw;
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, ex.getMessage(), ex);
}
}
instantiate()
方法的实现如下:
// org/springframework/beans/factory/support/SimpleInstantiationStrategy.java
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
if (!bd.hasMethodOverrides()) {
// ...
// 利用构造方法进行实例化
return BeanUtils.instantiateClass(constructorToUse);
}
else {
// ...
// 存在方法覆写,利用 CGLIB 来完成实例化,需要依赖于 CGLIB 生成子类
return instantiateWithMethodInjection(bd, beanName, owner);
}
}
Bean 属性注入
populateBean(beanName, mbd, instanceWrapper)
:负责进行属性设值,处理依赖。
其代码实现如下:
initializeBean
initializeBean(beanName, exposedObject, mbd)
:处理各种回调。
属性注入完成后,这一步其实就是处理各种回调了,这块代码比较简单。
其代码实现如下:
参考:
标签:容器,beanFactory,Spring,beanName,剖析,Bean,BeanFactory,beans,IoC From: https://www.cnblogs.com/larry1024/p/17942592