Spring引导bean null异常

时间:2017-01-07 12:09:49

标签: spring spring-boot spring-bean

@SpringBootApplication
public class DataProcessorApplication {
   public static void main(String[] args) throws UnknownHostException {
   SpringApplication app = new SpringApplication(DataProcessorApplication.class);
   app.run();
}

PostProcessor类

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class BeanRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {

  private static final Logger LOG = LoggerFactory.getLogger(BeanRegistryPostProcessor.class);

  @Autowired
  private DataConfigurationService dataConfigurationService;

  @Override
  public void postProcessBeanFactory(final ConfigurableListableBeanFactory factory)
      throws BeansException {
    // we don't want to touch existing beans
  }

  @Override
  public void postProcessBeanDefinitionRegistry(final BeanDefinitionRegistry registry){
    dataConfigurationService.something(); // service bean is null here
  }
}

我的服务类

@Service
public class DataConfigurationService implements ApplicationListener<ApplicationReadyEvent> {

  private static final Logger LOG = LoggerFactory.getLogger(DataConfigurationService.class);

  @Override
  public void onApplicationEvent(final ApplicationReadyEvent e) {
    LOG.debug("Loading active DataConfiguration instance...");
  }
}

异常

java.lang.NullPointerException: null
    at dataprocessor.configmodels.processor.BeanRegistryPostProcessor.postProcessBeanDefinitionRegistry(BeanRegistryPostProcessor.java:40)
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:118)
    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:685)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:523)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:736)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:369)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:313)
    at dataprocessor.DataProcessorApplication.main(DataProcessorApplication.java:47)

2017-01-07 12:42:47.802  WARN 8880 --- [           main] ationConfigEmbeddedWebApplicationContext : Exception thrown from LifecycleProcessor on context close

java.lang.IllegalStateException: LifecycleProcessor not initialized - call 'refresh' before invoking lifecycle methods via the context: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@7a138fc5: startup date [Sat Jan 07 12:42:46 CET 2017]; root of context hierarchy
    at org.springframework.context.support.AbstractApplicationContext.getLifecycleProcessor(AbstractApplicationContext.java:416)
    at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:1004)
    at org.springframework.context.support.AbstractApplicationContext.close(AbstractApplicationContext.java:963)
    at org.springframework.boot.SpringApplication.handleRunFailure(SpringApplication.java:793)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:324)
    at dataprocessor.DataProcessorApplication.main(DataProcessorApplication.java:47)

2017-01-07 12:42:47.803 ERROR 8880 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Destroy method on bean with name 'org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory' threw an exception

java.lang.IllegalStateException: ApplicationEventMulticaster not initialized - call 'refresh' before multicasting events via the context: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@7a138fc5: startup date [Sat Jan 07 12:42:46 CET 2017]; root of context hierarchy
    at org.springframework.context.support.AbstractApplicationContext.getApplicationEventMulticaster(AbstractApplicationContext.java:403)
    at org.springframework.context.support.ApplicationListenerDetector.postProcessBeforeDestruction(ApplicationListenerDetector.java:97)
    at org.springframework.beans.factory.support.DisposableBeanAdapter.destroy(DisposableBeanAdapter.java:233)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroyBean(DefaultSingletonBeanRegistry.java:578)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingleton(DefaultSingletonBeanRegistry.java:554)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingleton(DefaultListableBeanFactory.java:951)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingletons(DefaultSingletonBeanRegistry.java:523)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingletons(DefaultListableBeanFactory.java:958)
    at org.springframework.context.support.AbstractApplicationContext.destroyBeans(AbstractApplicationContext.java:1035)
    at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:1011)
    at org.springframework.context.support.AbstractApplicationContext.close(AbstractApplicationContext.java:963)
    at org.springframework.boot.SpringApplication.handleRunFailure(SpringApplication.java:793)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:324)
    at dataprocessor.DataProcessorApplication.main(DataProcessorApplication.java:47)

POM

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.0.BUILD-SNAPSHOT</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>

1 个答案:

答案 0 :(得分:0)

Spring在下一个序列中初始化上下文:

首先,基于应用程序配置和自动检测的类(@Component@Service等),将在BeanDefinitionRegistry中创建并注册bean定义。

之后,Spring会自动检测在bean定义中实现BeanFactoryPostProcessor的bean,并在创建任何其他bean之前应用它们。由于BeanRegistryPostProcessorBeanFactoryPostProcessor的实施,因此将在此步骤中应用它。

之后Spring将自动检测实现BeanPostProcessor接口的所有bean,并将它们应用于随后创建的任何bean。其中一个bean是AutowiredAnnotationBeanPostProcessor,它处理@Autoware注释。这意味着您的服务将在此步骤中注入。

如您所见,在将DataConfigurationService bean注入BeanRegistryPostProcessor之前,您正尝试使用它。要解决此问题,您可以在ApplicationContextAware中实现BeanRegistryPostProcessor接口,然后直接从应用程序上下文获取服务实例:

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class BeanRegistryPostProcessor 
    implements BeanDefinitionRegistryPostProcessor, ApplicationContextAware{

    private ApplicationContext applicationContext;

    ...

    @Override
    public void postProcessBeanDefinitionRegistry(final BeanDefinitionRegistry registry){
      DataConfigurationService service = applicationContext.getBean(DataConfigurationService.class);
      service.something();
    }

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

有关所谓的容器扩展点的更多详细信息,您可以在Spring documentation中找到。