Spring Bean的生命周期是什么样的?
在Spring容器里一个Bean的从创建到销毁一般都是经历了以下几个阶段:
定义阶段(Bean元信息配置)=>实例化阶段(创建Bean对象)=>初始化阶段(执行初始化逻辑)=>使用阶段(Bean可用)=>销毁阶段(释放资源)
定义阶段(BeanDefinition解析)
Spring通过配置(XML、注解、Java配置)解析Bean的元数据,生成BeanDefinition对象。
BeanDefinition存储了Bean的类名、作用域(scope)、依赖项(depends-on)、初始化方法、销毁方法等元数据。
所有BeanDefinition存储在容器的BeanDefinitionMap(一个HashMap)中,键为Bean名称,值为BeanDefinition对象。
解析器:
- XML配置:XmlBeanDefinitionReader解析标签。
- 注解配置:ClassPathBeanDefinitionScanner扫描@Component等注解。
- Java配置:ConfigurationClassPostProcessor解析@Bean方法。
实例化阶段(创建Bean实例)
根据BeanDefinition通过反射或工厂方法创建Bean实例(对象),但此时属性未注入。
默认通过无参构造方法实例化(若未指定,Spring会强制要求无参构造)。
在AbstractAutowireCapableBeanFactory类中的createBeanInstance方法中实现。
属性值填充(依赖注入)
为Bean的属性设置值或注入依赖。
- 通过@Autowired、@Value、XML的等方式注入属性。
- 若注入的依赖是其他Bean,会递归触发依赖Bean的生命周期。
- 循环依赖问题:在属性注入阶段处理循环依赖(通过三级缓存解决)。
在AbstractAutowireCapableBeanFactory的populateBean方法中处理。
Aware接口回调设置
若Bean实现了特定Aware接口,Spring会回调对应方法,注入容器相关对象。
- BeanNameAware:注入Bean在容器中的名称(setBeanName(String beanName))。
- BeanFactoryAware:注入当前Bean所在的BeanFactory(setBeanFactory(BeanFactory beanFactory))。
- ApplicationContextAware:若容器是ApplicationContext,注入应用上下文(setApplicationContext(ApplicationContext applicationContext))。
在AbstractAutowireCapableBeanFactory的initializeBean方法中调用。
BeanPostProcessor前置处理
在Bean初始化前,允许自定义BeanPostProcessor对Bean实例进行处理。
主要是调用BeanPostProcessor的postProcessBeforeInitialization方法。
常见的实现类
- ApplicationContextAwareProcessor:处理ApplicationContextAware接口。
- InitDestroyAnnotationBeanPostProcessor:处理@PostConstruct注解。
由AbstractAutowireCapableBeanFactory的applyBeanPostProcessorsBeforeInitialization方法执行。
InitializingBean处理以及自定义init-method处理
执行Bean的初始化逻辑。
InitializingBean处理,在所有Bean属性设置完成后进行初始化操作。如果Bean实现了InitializingBean接口,InitializingBean的afterPropertiesSet方法会被调用。
自定义init-method处理,如果Bean在配置文件中定义了初始化方法那么该方法会被调用。
例如:通过XML配置init-method或Java配置@Bean(initMethod="xxx")。
在AbstractAutowireCapableBeanFactory的invokeInitMethods方法中调用
BeanPostProcessor后置处理
在Bean初始化后,允许自定义BeanPostProcessor对Bean实例进行处理。
BeanPostProcessor的postProcessAfterInitialization方法会被调用。
常见用途:AOP代理(如AbstractAutoProxyCreator在此阶段为目标对象创建代理)。
由AbstractAutowireCapableBeanFactory的applyBeanPostProcessorsAfterInitialization方法执行
注册DisposableBean回调
如果Bean实现了DisposableBean接口或在Bean定义中指定了自定义的销毁方法,Spring容器会为这些Bean注册一个销毁回调,确保在容器关闭时能够正确地清理资源。
在AbstractAutowireCapableBeanFactory类中的registerDisposableBeanlfNecessary方法中实现
Bean使用阶段
Bean已完全初始化,可被应用程序使用。通过依赖注入获取Bean实例(如@Autowired或ApplicationContext.getBean())。
此阶段Bean处于“可用”状态,直到容器关闭。
Bean销毁阶段
容器关闭时,释放Bean资源。
主要步骤:
- 接口回调:若Bean实现了DisposableBean,调用destroy方法。
- 注解:若方法标注了@PreDestroy,Spring会调用该方法。
- 自定义销毁方法:通过XML配置destroy-method或Java配置@Bean(destroyMethod="xxx")。
- 资源释放:如关闭数据库连接、释放文件句柄等。
在DisposableBeanAdapter的destroy方法中实现
总结
通过代码出处,可以观察到整个Bean的创建的过程都依赖于AbstractAutowireCapableBeanFactory这个类,而销毁主要依赖DisposableBeanAdapter这个类。
AbstractAutowireCapableBeanFactory 的入口处,doCreateBean的核心代码如下,其中包含了实例化、设置属性值、初始化Bean以及注册销毁回调的几个核心方法。
这里就不贴代码了,想更深入看细节的可以去看源码。
Spring中创建Bean的方式有哪些?
基于注解的自动扫描
通过注解标记类,并配合组件扫描实现自动注册。
常见的注解有
@Component, @Service, @Repository, @Controller(及其衍生注解)。
例如:当在类上添加@Component时,再在配置类或 XML 中启用组件扫描(@ComponentScan 或 )。这个类在服务启动时会自动被扫描到,然后注入到Spring容器。- @Configuration
- @ComponentScan("com.jimoer.service")
- public class BeanConfig {
- }
复制代码- @Service
- public class UserService {
- public void hello() {
- System.out.println("Hello from UserService");
- }
- }
- @Component
- public class UserHandler {
- public void hello() {
- System.out.println("Hello from UserHandler");
- }
- }
- @Repository
- public class UserRepository {
- public void hello() {
- System.out.println("Hello from UserRepository");
- }
- }
- @Controller
- public class UserController {
- public void hello() {
- System.out.println("Hello from UserController");
- }
- }
复制代码 使用@Configuration与@Bean 注解
通过 @Configuration 标注的配置类,显式定义 Bean 的创建逻辑。
适用于:需要精确控制 Bean 的初始化逻辑(如依赖其他 Bean 或复杂条件)。- @Configuration
- public class AppConfig {
- @Bean
- public UserService userService() {
- return new UserService();
- }
- }
复制代码 XML 配置文件
通过 xml 的方式来定义 Bean。
在SpringBoot 流行以前,这种方式挺多的, SpringBoot 流行起来之后,这么用的越来越少了。- <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="userService" >
- <property name="message" value="Hello Spring!" />
- </bean>
- </beans>
复制代码 接下来,我们将Spring配置中注册这个自定义的作用域。
这可以通过ConfigurableBeanFactory.registerScope 方法实现。- ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
- UserService userService = context.getBean("userService");
复制代码 此时在Bean定义中使用自定义的作用域的名称jimoer。
Spring 容器将会根据你的自定义逻辑来创建和管理这些 Bean。- @Import({UserServiceImpl.class})
- @Configuration
- public class UserBeanConfiguration {
- }
复制代码
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |