How does Spring Boot allow its own beans to be loaded first

background introduction

In some requirements, there may be certain scenarios, such as loading your own beans first, and then doing some DB operations on your own beans to initialize configuration issues, and then the subsequent beans continue to do other business logic based on this configuration file. Hence the title of this article.

Implementation

DependsOn annotation

There are many ways to implement this @DependsOn online. If the number of dependent beans is small, it is easier to handle, but when the number increases, it will be more troublesome. Each class needs to be rewritten, so the second method is recommended.

ApplicationContextInitializer

After registering ApplicationContextInitializer, you can register BeanDefinitionRegistryPostProcessor into Spring. Finally, implement BeanDefinitionRegistryPostProcessor to register the target bean.

 class DemoApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
    
    

  @Override
  public void initialize(ConfigurableApplicationContext applicationContext) {
    
    
    
      applicationContext.addBeanFactoryPostProcessor(new DemoBeanDefinitionRegistryPostProcessor());
  }
}

Implement BeanDefinitionRegistryPostProcessor:

public class DemoBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor, PriorityOrdered {
    
    
  // from BeanDefinitionRegistryPostProcessor interface
  @Override
  public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
    
    
// 重点在这里,这里可以把自己的 想要提起 实现的 或者初始化的 bean  加到这里
beanDefinitionRegistry.registerBeanDefinition("DemoService",new RootBeanDefinition(DemoService.class));
  }

  // from BeanDefinitionRegistryPostProcessor interface
  @Override
  public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
    
    

  }

// from PriorityOrdered  interface
  @Override
  public int getOrder() {
    
    
  // 排在 ConfigurationClassPostProcessor 之前即可
      return Ordered.LOWEST_PRECEDENCE - 1;
  }
}

It should be noted here that you cannot use @Componet or other annotations to register BeanDefinitionRegistryPostProcessor.

Because the @Componet annotation method can be registered on the premise that it is scanned by ConfigurationClassPostProcessor, and now, we need to consider our bean registration, which must be before these beans, so it must not be managed by "it-ConfigurationClassPostProcessor". Thinking from another angle, if the bean registered by "it" management class must not be ranked in front of ConfigurationClassPostProcessor.

Note: @Order can only control the order of spring's own beans, and cannot control the annotations of @Service @Component and @Repository.

simple demo

Requirement: The author wants TestService to be registered in advance, and after execution, other beans can be registered.

public class TestService {
    
    
    // 存放系统配置
    private static Map<String, String> GLOBAL_CONF = new HashMap<>();

    @PostConstruct
    public void init() {
    
    
        // 先做初始化 GLOBAL_CONF 或者其他 IO操作
        // GLOBAL_CONF.put(key, value);
    }
    //其他 bean 通过这个方法获得系统配置
    public static String getGlobalConfig(String key) {
    
    
        return GLOBAL_CONF.get(key);
    }
}

Implementation: (for simplicity, directly implement the above three interfaces)

public class DemoBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor, 
PriorityOrdered, 
ApplicationContextInitializer<ConfigurableApplicationContext> {
    
    

    /**
     *  第二步: 注册 自己的 bean
     *
     * @param beanDefinitionRegistry
     */
    // from BeanDefinitionRegistryPostProcessor interface
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
    
    
        beanDefinitionRegistry.registerBeanDefinition("TestService",new RootBeanDefinition(TestService.class));
    }

    // from BeanDefinitionRegistryPostProcessor interface
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
    
    

    }

// from PriorityOrdered  interface
    @Override
    public int getOrder() {
    
    
        return Ordered.LOWEST_PRECEDENCE - 1;
    }

    /**
     *  第一步 先注册 到 configurableApplicationContext 中
     *
     * @param configurableApplicationContext
     */
    // from ApplicationContextInitializer  interface
    @Override
    public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
    
    
        configurableApplicationContext.addBeanFactoryPostProcessor(new DemoBeanDefinitionRegistryPostProcessor());
    }
}

Thinking : How to get or see the order in which spring beans are loaded?
See next article .

Guess you like

Origin blog.csdn.net/qq_39463175/article/details/129460897