SpringBoot - Bean创建顺序和PostConstruct初始化

时间:2018-06-05 12:34:42

标签: maven spring-boot initialization javabeans spring-annotations

我有一个maven多模块SpringBoot Web应用程序。我有一个名为 config-module 的子模块,它有一个配置类:

@Configuration
public class PropertiesConfig {

    @Bean
    public YamlPropertiesFactoryBean errorPropertiesFromYamlFile() {
        final YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
        yaml.setResources(new ClassPathResource("errorMessages.yml"));
        return yaml;
    }

}

我有一个 web-app-module maven模块,它将以前的 config-module 作为依赖项,并作为导入的spring应用程序。

在这个主模块中,我还有一个加载新属性的配置类:

@Configuration
public class WebPropertiesConfig {

    @Bean
    public YamlPropertiesFactoryBean webPropertiesFromYamlFile() {
        final YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
        yaml.setResources(new ClassPathResource("webProperties.yml"));
        return yaml;
    }

}

在这个模块中我也有这样一个类:

@Component
@ConfigurationProperties(prefix = "webpart")
public class ConfigPropertiesMapper {

    @PostConstruct
    public void init() {
        //do something here
    }

}

而且我不知道它来自哪里,但初始化的实际顺序是这个(我在调试模式下检查过):

  1. PropertiesConfig.errorPropertiesFromYamlFile()从中创建bean config-module
  2. ConfigPropertiesMapper.init() PostConstruct初始化 web应用模块
  3. WebPropertiesConfig.webPropertiesFromYamlFile()从中创建bean web应用模块
  4. 为什么?我怎么能把顺序设置为这个?:

    1. PropertiesConfig.errorPropertiesFromYamlFile()
    2. WebPropertiesConfig.webPropertiesFromYamlFile()
    3. ConfigPropertiesMapper.init()
    4. 我尝试使用@Order@Qualifier@Primary注释,但我无法解决此问题。

      我知道另外一个注释:@DependsOn。但老实说,我不想使用它,因为我需要将这个注释添加到每个有@PostConstruct的方法上。

2 个答案:

答案 0 :(得分:1)

来自API documentation

“虽然此类订单值可能影响注入点的优先级,但请注意它们不会影响单例启动顺序,这是由依赖关系和@DependsOn声明(影响运行时确定的依赖关系图)确定的正交关注点。”

您需要@DependsOn注释才能控制创建顺序。

或者在一个bean中调用所有init方法,以便控制顺序。如果您注入其他bean,您将确定它们已完成创建。

类似的东西:

@Component
public class InitBean {

   @Autowired
   privaPropertiesConfig propertiesConfig;

   @Autowired
   private WebPropertiesConfig webPropertiesConfig;

   @Autowired
   private ConfigPropertiesMapper configPropertiesMapper;

   @PostConstruct
   public void init() {
       propertiesConfig.errorPropertiesFromYamlFile()
       webPropertiesConfig.webPropertiesFromYamlFile()
       configPropertiesMapper.init()    
    }
}

但是你应该把你所有的属性添加到一个类中,spring会找到它可以做的,忽略它不能用的东西,并且webProperties会覆盖errroMessages中的任何值重复值。

@Component
@PropertySource(value={ "classpath:errorMessages.yml", "classpath:webProperties.yml"}, ignoreResourceNotFound="true))
@ConfigurationProperties(prefix = "webpart")
public class ConfigPropertiesMapper {
   ...    
}

答案 1 :(得分:0)

在Spring / Boot中,bean 初始化(不是bean creation )有不同的机制。可以根据需要使用它们,而与Bean的依赖关系无关。

顺序(2020年春季发布,带有Spring Boot 2.3.2)是

  1. 使用@PostConstructInitializingBean进行直接bean初始化
  2. SmartInitializingSingleton s
  3. SmartLifecycle
  4. ApplicationStartedEvent被触发
  5. ApplicationReadyEvent被触发

(当然,还有其他事件)