说说@PostConstruct、init-method和afterPropertiesSet执行顺序?
1 个回答
首先你要快乐,其次都是其次。古薰儿在 Spring 框架中,`@PostConstruct`、`init-method` 和 `afterPropertiesSet` 的执行顺序是: **构造函数 > @PostConstruct > afterPropertiesSet > init-method** #### **每个初始化方式的介绍** 1. **`@PostConstruct`** - 来源:`javax.annotation` 包(Spring Boot 3.0 之后为 `jakarta.annotation`)。 - 作用:标注的方法会在依赖注入完成后执行。 - 使用场景:适用于初始化资源或设置默认值。 2. **`afterPropertiesSet`** - 来源:Spring 的 `InitializingBean` 接口。 - 作用:Spring 在初始化阶段会调用此方法。 - 使用场景:对依赖注入后的属性进行额外处理。 3. **`init-method`** - 来源:通过 XML 配置或 `@Bean` 注解指定。 - 作用:指定初始化完成后调用的方法。 - 使用场景:灵活配置自定义的初始化逻辑。 #### **执行顺序的源码分析** Spring 的 **Bean 初始化流程** 包括以下阶段: 1. **实例化**:调用构造函数创建 Bean 对象。 2. **设置属性值**:通过依赖注入将属性赋值。 3. **调用 `@PostConstruct` 方法**。 4. **调用 `InitializingBean` 的 `afterPropertiesSet` 方法**。 5. **调用配置的 `init-method` 方法**。 Spring 通过 `initializeBean` 方法实现这些逻辑: ```java protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) { // 调用 @PostConstruct 方法 applyBeanPostProcessorsBeforeInitialization(bean, beanName); // 调用 InitializingBean 的 afterPropertiesSet 方法 invokeInitMethods(beanName, wrappedBean, mbd); return bean; } ``` 1. `applyBeanPostProcessorsBeforeInitialization` 调用 `BeanPostProcessor`,如 `InitDestroyAnnotationBeanPostProcessor`,执行 `@PostConstruct` 标注的方法。 2. `invokeInitMethods` 顺序调用 `afterPropertiesSet` 和 `init-method`。 #### **示例代码** ```java import jakarta.annotation.PostConstruct; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.stereotype.Component; @Component public class DemoBean implements InitializingBean { public DemoBean() { System.out.println("1. 构造函数被调用"); } @PostConstruct public void postConstruct() { System.out.println("2. @PostConstruct 方法被调用"); } @Override public void afterPropertiesSet() { System.out.println("3. afterPropertiesSet 方法被调用"); } public void customInitMethod() { System.out.println("4. init-method 方法被调用"); } } @Configuration class Config { @Bean(initMethod = "customInitMethod") public DemoBean demoBean() { return new DemoBean(); } } ``` **输出结果** ``` 1. 构造函数被调用 2. @PostConstruct 方法被调用 3. afterPropertiesSet 方法被调用 4. init-method 方法被调用 ``` #### **顺序背后的原理** 1. `@PostConstruct` 由 `CommonAnnotationBeanPostProcessor` 处理,依赖注入完成后执行。 2. `afterPropertiesSet` 在 `invokeInitMethods` 方法的第一步执行。 3. `init-method` 在 `invokeInitMethods` 方法的第二步执行。 #### **总结** 1. 执行顺序:构造函数 > `@PostConstruct` > `afterPropertiesSet` > `init-method`。 2. 使用建议: - 推荐使用 `@PostConstruct`,简洁且紧耦合。 - `afterPropertiesSet` 适合实现接口的场景。 - `init-method` 更灵活,适用于 XML 或 Java 配置中。编辑于 2024-11-25 14:07 •IP属地 美国举报评论收藏
公众号进入网站体验更佳

