--- date: 2024-02-02 --- # 版本说明 > 💡 本文使用的版本为: > - JDK: 17 >- Spring Boot: 3.1.7 # 生命周期 整体流程: ```mermaid graph TD BEGIN[Spring 加载 Bean] --> A[1. 实例化 Bean] A -->B[2. 填充 Bean 属性] B -->C[3. 初始化 Bean] C -->D[4. 销毁 Bean] ``` 几点说明: 1. ` 实例化 Bean`:此时 Bean 只实例化,并没有进行 @Autowired 属性填充。 2. ` 填充 Bean 属性 `:如果 Bean 的属性有 @Autowired 注解,会进行属性填充。 3. ` 初始化 Bean` 4. ` 销毁 Bean`:如果 Bean 实现了 DisposableBean 接口,会调用 destroy 方法。 分析一下 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean 方法,主体代码如下: ```java protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } // 1:默认调用无参构造实例化 Bean // 如果是只有带参数的构造方法,构造方法里的参数依赖注入,就是发生在这一步 if (instanceWrapper == null) { instanceWrapper = createBeanInstance(beanName, mbd, args); } // Eagerly cache singletons to be able to resolve circular references // even when triggered by lifecycle interfaces like BeanFactoryAware. boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } // Initialize the bean instance. Object exposedObject = bean; try { // 2:填充属性(DI 依赖注入发生在此步骤) populateBean(beanName, mbd, instanceWrapper); // 3:调用初始化方法,完成 bean 的初始化操作(AOP 的第三个入口) exposedObject = initializeBean(beanName, exposedObject, mbd); } catch (Throwable ex) { // ... } // ... ``` 首先通过一个测试用例,了解 Spring Bean 的生命周期。下面定义了一个 LifeBean: ```java @Component @Data @Slf4j public class LifeBean implements BeanNameAware, BeanClassLoaderAware, InitializingBean, DisposableBean { private int i; @PostConstruct public void init() { log.info("LifeBean init ..."); } @Override public void setBeanName(String s) { log.info("LifeBean setBeanName {}", s); } @Override public void setBeanClassLoader(ClassLoader classLoader) { log.info("LifeBean setBeanClassLoader {}", classLoader); } @Override public void afterPropertiesSet() { log.info("LifeBean afterPropertiesSet i = {}", i); } @Override public void destroy() { log.info("LifeBean destroy ..."); } } ``` 单元测试代码: ```java @Test public void testLife() { LifeBean bean = context.getBean(LifeBean.class); bean.setI(1); } ``` IDE 增加 debug 断点,并加上 Condition: ```java "lifeBean".equalsIgnoreCase(beanName) ```  log 输出: ``` LifeBean setBeanName lifeBean LifeBean setBeanClassLoader jdk.internal.loader.ClassLoaders$AppClassLoader@55f96302 LifeBean init ... LifeBean afterPropertiesSet i = 0 LifeBean destroy ... ``` ## 初始化 Bean 详细流程  ### invokeAwareMethods ```java private void invokeAwareMethods(String beanName, Object bean) { if (bean instanceof Aware) { // 1. setBeanName if (bean instanceof BeanNameAware beanNameAware) { beanNameAware.setBeanName(beanName); } // 2. setBeanClassLoader if (bean instanceof BeanClassLoaderAware beanClassLoaderAware) { ClassLoader bcl = getBeanClassLoader(); if (bcl != null) { beanClassLoaderAware.setBeanClassLoader(bcl); } } // 3. setBeanFactory if (bean instanceof BeanFactoryAware beanFactoryAware) { beanFactoryAware.setBeanFactory(AbstractAutowireCapableBeanFactory.this); } } } ``` ### applyBeanPostProcessorsBeforeInitialization ```java @Override public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor processor : getBeanPostProcessors()) { Object current = processor.postProcessBeforeInitialization(result, beanName); if (current == null) { return result; } result = current; } return result; } ``` ### invokeInitMethods ```java protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd) throws Throwable { boolean isInitializingBean = (bean instanceof InitializingBean); // 1. afterPropertiesSet if (isInitializingBean && (mbd == null || !mbd.hasAnyExternallyManagedInitMethod("afterPropertiesSet"))) { if (logger.isTraceEnabled()) { logger.trace("Invoking afterPropertiesSet() on bean with name'" + beanName + "'"); } ((InitializingBean) bean).afterPropertiesSet(); } // 2. 指定 init-method 方法 if (mbd != null && bean.getClass() != NullBean.class) { String[] initMethodNames = mbd.getInitMethodNames(); if (initMethodNames != null) { for (String initMethodName : initMethodNames) { if (StringUtils.hasLength(initMethodName) && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) && !mbd.hasAnyExternallyManagedInitMethod(initMethodName)) { invokeCustomInitMethod(beanName, bean, mbd, initMethodName); } } } } } ``` ### applyBeanPostProcessorsAfterInitialization ```java @Override public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor processor : getBeanPostProcessors()) { Object current = processor.postProcessAfterInitialization(result, beanName); if (current == null) { return result; } result = current; } return result; } ``` ## BeanFactory BeanFactory 接口文件上的注释如下。里面包含了 bean 的生命周期以及对应的顺序。  [Spring 官方文档:Customizing the Nature of a Bean](https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-factory-nature)  # Scope [Spring 官方文档 #Bean Scopes](https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-factory-scopes)  通过官方文档可以看到,一共有 6 种类型的 Scope: 1. `singleton`:(` 默认 `)每个 Spring IoC 容器中仅有一个实例(单例)。 2. `prototype`:每次注入都会新建一个对象,Spring IoC 容器并不会缓存 prototype 的 bean。 3. `request`:仅在 web-aware 时生效,每次 `HTTP` 请求都会新建一个对象。 4. `session`:仅在 web-aware 时生效,每次 `HTTP Session` 都会新建一个对象。 5. `application`:仅在 web-aware 时生效,每次 `ServletContext` 都会新建一个对象。 6. `websocket`:仅在 web-aware 时生效,每次 `WebSocket` 都会新建一个对象。 ```java public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement { /** * Scope identifier for the standard singleton scope: {@value}. *
Note that extended bean factories might support further scopes. * @see #setScope * @see ConfigurableBeanFactory#SCOPE_SINGLETON */ String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON; /** * Scope identifier for the standard prototype scope: {@value}. *
Note that extended bean factories might support further scopes.
* @see #setScope
* @see ConfigurableBeanFactory#SCOPE_PROTOTYPE
*/
String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
```
## Scope 使用示例
SingletonBean 是一个 Singleton Scope 的 bean,里面的 Scope 注解不设置也可以,默认是 Singleton 的。
```java
@Component
@Scope
@Data
@Slf4j
public class SingletonBean {
private int i;
@PostConstruct
public void init() {
log.info("SingletonBean init ...");
}
}
```
ProtoTypeBean 是一个 Prototype Scope 的 bean。
```java
@Component
@Scope(scopeName = SCOPE_PROTOTYPE)
@Data
@Slf4j
public class ProtoTypeBean {
private int i;
@PostConstruct
public void init() {
log.info("ProtoTypeBean init ...");
}
}
```
测试代码中对于每个 bean,分别从容器中获取 2 次,看 log 输出。
```java
@RunWith(SpringRunner.class)
@Slf4j
@SpringBootTest(classes = Application.class)
public class BeanTest {
@Autowired
private ApplicationContext context;
@Test
public void testScope() {
context.getBean(SingletonBean.class);
context.getBean(SingletonBean.class);
context.getBean(ProtoTypeBean.class);
context.getBean(ProtoTypeBean.class);
}
}
```
最终输出了 1 次 SingletonBean,2 次 ProtoTypeBean,说明 SingletonBean 是单例的,ProtoTypeBean 是每次注入都会新建一个对象。
```
SingletonBean init ...
ProtoTypeBean init ...
ProtoTypeBean init ...
```
## 源码分析
在 Scope 注解定义上查找引用,发现 Scope 作为实例变量只有 AnnotationScopeMetadataResolver 中。
```java
public class AnnotationScopeMetadataResolver implements ScopeMetadataResolver {
private final ScopedProxyMode defaultProxyMode;
protected Class extends Annotation> scopeAnnotationType = Scope.class;
```
```java
@Override
public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
ScopeMetadata metadata = new ScopeMetadata();
if (definition instanceof AnnotatedBeanDefinition) {
AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(
annDef.getMetadata(), this.scopeAnnotationType);
if (attributes != null) {
metadata.setScopeName(attributes.getString("value"));
ScopedProxyMode proxyMode = attributes.getEnum("proxyMode");
if (proxyMode == ScopedProxyMode.DEFAULT) {
proxyMode = this.defaultProxyMode;
}
metadata.setScopedProxyMode(proxyMode);
}
}
return metadata;
}
```
为了观察 Spring 如何处理 SingletonBean 的 Scope 注解,我们可以在这里加一个断点调试,Condition 是 `Objects.equals("yano.spring.bean.SingletonBean", annDef.getBeanClassName())`。

接着一步步断点向上调试,最终会调用到 org.springframework.context.annotation.ClassPathBeanDefinitionScanner#doScan。具体代码就不分析了,只要理解 Spring 框架,就能看懂源码。
```java
protected Set Checks already instantiated singletons and also allows for an early
* reference to a currently created singleton (resolving a circular reference).
* @param beanName the name of the bean to look for
* @param allowEarlyReference whether early references should be created or not
* @return the registered singleton object, or {@code null} if none found
*/
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// Quick check for existing instance without full singleton lock
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
synchronized (this.singletonObjects) {
// Consistent creation of early reference within full singleton lock
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
ObjectFactory> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
```
## Spring Boot 2.6.0 开启循环依赖
> 💡 并不建议这样做,程序最好就没有循环依赖。
项目启动的时候添加参数 `spring.main.allow-circular-references=true`,或者在代码中添加:
```java
new SpringApplicationBuilder(Application.class).allowCircularReferences(true).run(args);
```
# GitHub LeetCode 项目
项目 [GitHub LeetCode 全解](https://github.com/LjyYano/LeetCode),欢迎大家 star、fork、merge,共同打造最全 LeetCode 题解!
[Java 编程思想 - 最全思维导图 - GitHub 下载链接](https://github.com/LjyYano/Thinking_in_Java_MindMapping),需要的小伙伴可以自取~!!!