老师总结的Bean生命周期

本文详细解析了Spring框架中Bean从创建到销毁的完整生命周期,包括实例化、依赖注入、初始化及销毁等关键阶段,深入探讨各阶段触发的接口回调与方法执行顺序。

>>>>Bean的生命周期

1.首先容器启动后,会对scope为singleton且非懒加载的bean进行实例化,

 

2.按照Bean定义信息配置信息,注入所有的属性,

 

3.如果Bean实现了BeanNameAware接口,会回调该接口的setBeanName()方法,传入该Bean的id,此时该Bean就获得了自己在配置文件中的id,

 

4.如果Bean实现了BeanFactoryAware接口,会回调该接口的setBeanFactory()方法,传入该Bean的BeanFactory,这样该Bean就获得了自己所在的BeanFactory,

 

5.如果Bean实现了ApplicationContextAware接口,会回调该接口的setApplicationContext()方法,传入该Bean的ApplicationContext,这样该Bean就获得了自己所在的ApplicationContext,

 

6.如果有Bean实现了BeanPostProcessor接口,则会回调该接口的postProcessBeforeInitialzation()方法,

 

7.如果Bean实现了InitializingBean接口,则会回调该接口的afterPropertiesSet()方法,

 

8.如果Bean配置了init-method方法,则会执行init-method配置的方法,

 

9.如果有Bean实现了BeanPostProcessor接口,则会回调该接口的postProcessAfterInitialization()方法,

 

10.经过流程9之后,就可以正式使用该Bean了,对于scope为singleton的Bean,Spring的ioc容器中会缓存一份该bean的实例,而对于scope为prototype的Bean,每次被调用都会new一个新的对象,期生命周期就交给调用方管理了,不再是Spring容器进行管理了

 

11.容器关闭后,如果Bean实现了DisposableBean接口,则会回调该接口的destroy()方法,

 

12.如果Bean配置了destroy-method方法,则会执行destroy-method配置的方法,至此,整个Bean的生命周期结束

 

Java是一种具备卓越性能与广泛平台适应性的高级程序设计语言,最初由Sun Microsystems(现属Oracle公司)的James Gosling及其团队于1995年正式发布。该语言在设计上追求简洁性、稳定性、可移植性以及并发处理能力,同时具备动态执行特性。其核心特征与显著优点可归纳如下: **平台无关性**:遵循“一次编写,随处运行”的理念,Java编写的程序能够在多种操作系统与硬件环境中执行,无需针对不同平台进行修改。这一特性主要依赖于Java虚拟机(JVM)的实现,JVM作为程序与底层系统之间的中间层,负责解释并执行编译后的字节码。 **面向对象范式**:Java全面贯彻面向对象的设计原则,提供对封装、继承、多态等机制的完整支持。这种设计方式有助于构建结构清晰、模块独立的代码,提升软件的可维护性与扩展性。 **并发编程支持**:语言层面集成了多线程处理能力,允许开发者构建能够同时执行多项任务的应用程序。这一特性尤其适用于需要高并发处理的场景,例如服务器端软件、网络服务及大规模分布式系统。 **自动内存管理**:通过内置的垃圾回收机制,Java运行时环境能够自动识别并释放不再使用的对象所占用的内存空间。这不仅降低了开发者在内存管理方面的工作负担,也有效减少了因手动管理内存可能引发的内存泄漏问题。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
<think>我们正在讨论Spring Bean生命周期,特别是构造函数、属性赋值和初始化方法的执行顺序。 根据提供的引用,我们可以总结如下: 1. 引用[1]提到属性赋值可以通过@Value、@Autowired等注解完成。 2. 引用[2]和[3]提到了init-method和destroy-method,以及使用注解@PostConstruct和@PreDestroy。 3. 引用[4]和[5]则提供了关于构造函数、afterPropertiesSet和init-method执行顺序的信息。 具体执行顺序为: 1. 首先调用构造函数来实例化Bean。 2. 然后进行属性赋值(例如通过setter方法或字段注入,使用@Autowired、@Resource等)。 3. 如果Bean实现了InitializingBean接口,则调用afterPropertiesSet()方法。 4. 接着调用自定义的初始化方法(通过@PostConstruct注解的方法或通过init-method指定的方法)。 注意:@PostConstruct注解的方法会在afterPropertiesSet()方法之前执行吗?实际上,根据Spring官方档: - @PostConstruct注解的方法会在依赖注入(即属性赋值)完成后被调用,并且在InitializingBean的afterPropertiesSet()方法之前以及init-method之前执行。 因此,更详细的顺序应该是: 1. 构造函数 2. 属性赋值(依赖注入) 3. @PostConstruct 注解的方法 4. InitializingBean的afterPropertiesSet()方法 5. 自定义的init-method方法 引用[4]中的例子是一个通过XML配置bean,它有一个构造器参数和一个init-method。在这个例子中,构造器先执行(传入参数),然后执行init-method。 引用[5]则说明了在构造函数中直接使用依赖注入的属性可能会出现问题,因为此时属性还没有被注入(即构造函数执行时,依赖注入还没有发生)。 所以,总结执行顺序为: 1. 构造函数(此时依赖还未注入,所以构造函数中不能使用依赖的属性) 2. 依赖注入(属性赋值) 3. 初始化回调(按顺序): a. 使用@PostConstruct注解的方法 b. 实现了InitializingBean接口的afterPropertiesSet()方法 c. 自定义的init-method(通过XML或@Bean(initMethod="...")指定) 验证:我们可以通过一个简单的例子来验证这个顺序。 例如,定义一个Bean: ```java public class ExampleBean implements InitializingBean { private String name; public ExampleBean() { System.out.println("1. 构造函数"); } public void setName(String name) { this.name = name; System.out.println("2. 属性赋值"); } @PostConstruct public void postConstruct() { System.out.println("3. @PostConstruct方法"); } @Override public void afterPropertiesSet() throws Exception { System.out.println("4. InitializingBean的afterPropertiesSet"); } public void initMethod() { System.out.println("5. 自定义的init-method"); } } ``` 在XML配置中: ```xml <bean id="exampleBean" class="ExampleBean" init-method="initMethod"> <property name="name" value="Spring"/> </bean> ``` 或者使用Java配置: ```java @Bean(initMethod = "initMethod") public ExampleBean exampleBean() { ExampleBean exampleBean = new ExampleBean(); exampleBean.setName("Spring"); return exampleBean; } ``` 输出顺序应该是: 1. 构造函数 2. 属性赋值 3. @PostConstruct方法 4. afterPropertiesSet 5. 自定义的init-method 因此,回答用户的问题:在Spring中,Bean的创建过程首先是调用构造函数,然后进行属性赋值(依赖注入),接着依次执行@PostConstruct注解的方法、InitializingBean接口的afterPropertiesSet方法,最后执行自定义的init-method方法。 注意:如果同时存在多种初始化方法,那么它们的执行顺序就是上面列出的顺序。 另外,关于销毁方法的顺序(与问题无关,但作为补充): 1. @PreDestroy注解的方法 2. DisposableBean接口的destroy()方法 3. 自定义的destroy-method方法 引用[3]中也提到了这些销毁方法。 所以,最终回答如下: </think>在Spring中,Bean的构造函数、属性赋值与初始化方法执行顺序遵循严格的生命周期规范,具体顺序如下: ### 执行顺序详解 1. **构造函数调用**(实例化) Spring首先调用Bean的构造函数创建对象实例。 **注意**:此时依赖注入尚未完成,构造函数内无法使用注入的属性(否则会抛`NullPointerException`)[^5]。 2. **属性赋值**(依赖注入) - 通过Setter方法(如`<property>`标签) - 或字段注入(如`@Autowired`、`@Resource`、`@Value`) 完成所有依赖项的注入[^1][^3]。 3. **初始化方法执行**(按顺序): a. **`@PostConstruct`注解方法** b. **`InitializingBean.afterPropertiesSet()`**(实现接口) c. **自定义`init-method`**(XML中`init-method`属性或`@Bean(initMethod)`)[^2][^3][^4] ### 顺序验证示例 ```java public class DemoBean implements InitializingBean { // 1. 构造函数先执行 public DemoBean() { System.out.println("构造函数执行"); } // 2. 属性注入(Setter或字段注入) @Autowired private Dependency dep; // 3a. 最先执行的初始化方法 @PostConstruct public void postConstruct() { System.out.println("@PostConstruct方法执行"); } // 3b. 接着执行接口方法 @Override public void afterPropertiesSet() { System.out.println("afterPropertiesSet()执行"); } // 3c. 最后执行自定义init-method public void customInit() { System.out.println("init-method方法执行"); } } ``` **输出顺序**: ``` 构造函数执行 @PostConstruct方法执行 afterPropertiesSet()执行 init-method方法执行 ``` ### 关键规则 1. **属性必须在构造函数之后注入**:构造函数中无法使用未初始化的依赖[^5]。 2. **初始化方法依赖注入结果**:所有初始化方法(`@PostConstruct`、`afterPropertiesSet()`、`init-method`)均可安全使用注入的属性[^3][^4]。 3. **销毁顺序**(补充): `@PreDestroy` → `DisposableBean.destroy()` → 自定义`destroy-method`[^3]。 > 此顺序由Spring IoC容器严格保证,确保依赖可用性和生命周期可控性[^1][^3][^4]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值