IOC bean的执行流程以及生命周期
先写一个dome
catBean对象
/**
* 功能描述:bean 对象
*
* @author Songxianyang
* @date 2022-05-13 15:42
*/
@Data
public class CatBean {
private String name;
}
spring-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="catBean" class="com.song.boot.springstudy.myspring.bean.CatBean">
<property name="name" value="洛洛"></property>
</bean>
</beans>
TestXmlSpring
/**
* 功能描述:学习 Spring 源码
*
* @author Songxianyang
* @date 2022-05-13 15:35
*/
public class TestXmlSpring {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
"spring-config.xml");
CatBean cat = (CatBean) context.getBean("catBean");
System.out.println(cat.getName());
}
}
org.springframework.context.support.AbstractApplicationContext#refresh()方法
setConfigLocations(configLocations); 显然装在我们的配置文件
Spring中的核心方法,会了它 你就会了全世界,哈哈哈
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// 准备此上下文以进行刷新。
prepareRefresh();
// 告诉子类刷新内部 bean 工厂。去获取工程中自己配置的bean
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 准备 bean 工厂以在此上下文中使用。 准备好自己工厂里面的bean
prepareBeanFactory(beanFactory);
try {
// 允许在上下文子类中对 bean 工厂进行后处理。
postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// 调用在上下文中注册为 bean 的工厂处理器。
invokeBeanFactoryPostProcessors(beanFactory);
//注册拦截 bean 创建的 bean 处理器。
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
// 为此上下文初始化消息源。
initMessageSource();
// 为此上下文初始化事件多播器
initApplicationEventMulticaster();
// 初始化特定上下文子类中的其他特殊 bean。
onRefresh();
// 检查侦听器 bean 并注册它们。
registerListeners();
//实例化所有剩余的(非惰性初始化)单例。
finishBeanFactoryInitialization(beanFactory);
//最后一步:发布相应的事件。
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// 销毁已经创建的单例以避免悬空资源。
destroyBeans();
// 重置“活动”标志。
cancelRefresh(ex);
// 将异常传播给调用者。
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
//重置 Spring 核心中的常见自省缓存,因为我们可能不再需要单例 bean 的元数据......
resetCommonCaches();
contextRefresh.end();
}
}
}
告诉子类刷新内部 bean 工厂。去获取工程中自己配置的bean
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
后续我们在跟到里面........这里先放在这里 。先大概再到具体分析
准备 bean 工厂以在此上下文中使用。 准备好自己工厂里面的bean
prepareBeanFactory(beanFactory);
大概意思就是:我们已经实例话一个bean工厂,但是这个beanFactory 并不是我们拿来就能用的。这个方法就是对这个beanFactory 上下问的初始化工作。有了这些初始化我们才能进行,系统环境才能使用这个beanFactory。
具体初始化了什么?
这个方法比较简单 我们就在这里说说:先看这段code 简明知意
/**
* Configure the factory's standard context characteristics,
* such as the context's ClassLoader and post-processors.
* @param beanFactory the BeanFactory to configure
* 配置工厂的标准上下文特征,例如上下文的 ClassLoader 和后处理器。 @param beanFactory 要配置的 BeanFactory
*/
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
// 告诉内部 bean 工厂使用上下文的类加载器等。
// 获取获取默认的类加载器 放进 bean工厂
beanFactory.setBeanClassLoader(getClassLoader());
if (!shouldIgnoreSpel) {
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
}
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
// 使用上下文回调配置 bean 工厂。 配置 环境、解析器、信息资源、上下文、类加载器 等等
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
beanFactory.ignoreDependencyInterface(ApplicationStartupAware.class);
// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
//BeanFactory 接口未在普通工厂中注册为可解析类型。 MessageSource 作为 bean 注册(并为自动装配找到)。
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// Register early post-processor for detecting inner beans as ApplicationListeners.
// 将用于检测内部 bean 的早期后处理器注册为 ApplicationListener。
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
// 检测 LoadTimeWeaver 并准备编织(如果找到)。
if (!NativeDetector.inNativeImage() && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// Register default environment beans.
// 给 bean 赋值默认的环境配置
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
}
}
初始化Bean工厂中的Bean对象 等方法
finishBeanFactoryInitialization(beanFactory);
重点来了 我们来分析 bean工厂,怎么获取bean工厂。加油奥里给
ConfigurableListableBeanFactory beanFactory =obtainFreshBeanFactory();
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
return getBeanFactory();
}
第一步 刷新bean 工厂
来分析
/**
* This implementation performs an actual refresh of this context's underlying
* bean factory, shutting down the previous bean factory (if any) and
* initializing a fresh bean factory for the next phase of the context's lifecycle.
*/
@Override
protected final void refreshBeanFactory() throws BeansException {
//先判断这个BeanFactory 是不是存在
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
//不存在 DefaultListableBeanFactory 就创建这种bean工厂
DefaultListableBeanFactory beanFactory = createBeanFactory();
// 序列化id 赋值
beanFactory.setSerializationId(getId());
// 可以不看这个方法 这个方法是定制bean工厂的方法 暂时用不上
customizeBeanFactory(beanFactory);
// 这个方法是实际干活的方法 :从配置文件xml中读取到我们定义的bean
loadBeanDefinitions(beanFactory);
this.beanFactory = beanFactory;
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
这是还没有执行 实际干活的方法
实际干活的方法:执行后
因为我在spring-config.xml 就配置了一个bean
给大家看一下 这个干活的实现方式 是什么样的
loadBeanDefinitions(beanFactory);
/**
* Loads the bean definitions via an XmlBeanDefinitionReader.
* @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
* @see #initBeanDefinitionReader
* @see #loadBeanDefinitions
*/
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
创建一个去读取XML的对象
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// Configure the bean definition reader with this context's
// resource loading environment.
下面是给对象赋值的一些操作
beanDefinitionReader.setEnvironment(this.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.
初始化bean的一个阅读器 去读
initBeanDefinitionReader(beanDefinitionReader);
实际去加载 xml 获取bean的方法,下面进行说明
loadBeanDefinitions(beanDefinitionReader);
}
实际去加载 xml 获取bean的方法,下面进行说明
loadBeanDefinitions(beanDefinitionReader);
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
这个方法 从Resource目录下面读到的xml 文件中的bean
Resource[] configResources = getConfigResources();
if (configResources != null) {
reader.loadBeanDefinitions(configResources);
}
我们给定字符串的 xml配置,一下进行说明
String[] configLocations = getConfigLocations();
if (configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
}
截图:
拿到配置后 就开始执行 读取这个配置文件xml
此时这个bean工厂创建成功 ,并返回。
在这里想一下 他怎么实例化并初始化我们在xml中配置的bean。我也不知道 接着跟代码(苦笑)
干活的代码,哈哈哈。也是断点的位置。
finishBeanFactoryInitialization(beanFactory);
beanFactory.preInstantiateSingletons();
this.getBean(beanName);
return this.doGetBean(name, (Class)null, (Object[])null, false);
return this.createBean(beanName, mbd, args);
// 获取bean 实例
beanInstance = this.doCreateBean(beanName, mbdToUse, args);
创建 bean 实例
instanceWrapper = this.createBeanInstance(beanName, mbd, args);
return ctors != null ? this.autowireConstructor(beanName, mbd, ctors, (Object[])null) : this.instantiateBean(beanName, mbd);
反射构造器
constructorToUse = clazz.getDeclaredConstructor();
实例化bean对象
return BeanUtils.instantiateClass(constructorToUse, new Object[0]);
分析它的执行流程。也是bean的初始化过程。
因为代码太多 我就在关键代码上打断点 给大家 解释
到这里 什么是 bean 的初始化
在这里说一下 。我们平时在 new 对象的时候 这么给对象赋值的。这个赋值的操作就是初始化工作。
那么仔细看 我那个catBean 这个对象 赋值赋值没。很显然 没有
那么怎么初始化 执行那段代码 可以执行对属性 的初始化工作
现在他来了
this.populateBean(beanName, mbd, instanceWrapper);