访问 BeanDefinitionRegistryPostProcessor 内部的 Spring ApplicationContext

Accessing Spring ApplicationContext inside of BeanDefinitionRegistryPostProcessor

如何访问 BeanDefinitionRegistryPostProcessor(BDRPP) 中的 ApplicationContext?我有以下 BDRPP。

public class MyCustomBeansFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor {

  @Override
  public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
    // Need to access ApplicationContext here
    System.out.println("Got Application Context: " + applicationContext);
  }

  @Override
  public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
  }
}

尝试添加@Autowired,甚至让我的 CustomBDRPP 实现 ApplicationContextAware,但 ApplicationContext 不是 injected/initialized。

public class MyCustomBeansFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor, ApplicationContextAware {

  //@Autowired
  private ApplicationContext applicationContext;

  public void setApplicationContext(ApplicationContext context) {
    applicationContext = context;
  }

  @Override
  public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
    System.out.println("Got Application Context: " + applicationContext);
  }

  @Override
  public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
  }
}

输出:

Got Application Context: null

如何实现?

您可以使用以下代码静态访问应用程序上下文

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;

@Service
public class BeanUtil implements ApplicationContextAware {

    private static ApplicationContext context;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        context = applicationContext;
    }
    public static <T> T getBean(Class<T> beanClass) {
        return context.getBean(beanClass);
    }
}

我有一个类似的任务并且将 BDRPP 声明为 Bean 有效:

public class MyCustomBdrpp implements BeanDefinitionRegistryPostProcessor {

  private ApplicationContext context;

  private MyCostomBdrpp(ApplicationContext context) {
    this.context = context;
  }

  @Override
  public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
    //foo
  }

  @Override
  public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
    //bar
  }
}

然后:

@Configuration
class MyConfig {

  @Bean
  public MyCustomBdrpp myBdrpp(@Autowired ApplicationContext context) {
    return new MyCustomBdrpp(context);
  }

}

但我需要说明一下,我是手动创建上下文的:

AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(MyConfig.class);
context.refresh();

这有效,至少在 Spring Boot 2.3.5 中是这样:

@Configuration
public class TestConfig implements BeanDefinitionRegistryPostProcessor, 
    ApplicationContextAware {

    private ApplicationContext context;

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        String driver = context.getEnvironment().getProperty("spring.datasource.driver-class-name");
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws 
BeansException {
        this.context = applicationContext;
    }
}