`NullPointerException` 由于自动装配失败

`NullPointerException` due to failed autowiring

我重构了 Spring doc for creating batch service 以实现我的 reader

的独立 class
@Component
@PropertySource("classpath:db-config.properties")
public class CsvReader<Item> extends FlatFileItemReader<Item>{

  @Autowired
  private Environment env;

  public CsvReader() {
    this.setResource(new ClassPathResource(env.getProperty("csv_file.name")));
    this.setLineMapper(new DefaultLineMapper<ImportDataItem>() {
      {
        setLineTokenizer(new DelimitedLineTokenizer() {
          {
            setNames(new String[] { "firstName", "lastName" });
          }
        });
      }
    });
  }
}

NullPointerExceptionenv.getProperty("csv_file.name") 抛出,如果用 String 文件名替换,它就可以工作。我读过 another answer 并且上面的代码看起来不错,所以你能帮我理解为什么 Environment env 没有自动装配吗?

[main] INFO org.springframework.context.annotation.AnnotationConfigApplicationContext - Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@5c29bfd: startup date [Thu Oct 22 11:26:18 IST 2015]; root of context hierarchy
[main] INFO org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader - Skipping bean definition for [BeanMethod:name=importDataJob,declaringClass=batch.spring.example.job.ImportDataJob]: a definition for bean 'importDataJob' already exists. This top-level bean definition is considered as an override.
[main] WARN org.springframework.context.annotation.ConfigurationClassEnhancer - @Bean method ScopeConfiguration.stepScope is non-static and returns an object assignable to Spring's BeanFactoryPostProcessor interface. This will result in a failure to process annotations such as @Autowired, @Resource and @PostConstruct within the method's declaring @Configuration class. Add the 'static' modifier to this method to avoid these container lifecycle issues; see @Bean javadoc for complete details.
[main] WARN org.springframework.context.annotation.ConfigurationClassEnhancer - @Bean method ScopeConfiguration.jobScope is non-static and returns an object assignable to Spring's BeanFactoryPostProcessor interface. This will result in a failure to process annotations such as @Autowired, @Resource and @PostConstruct within the method's declaring @Configuration class. Add the 'static' modifier to this method to avoid these container lifecycle issues; see @Bean javadoc for complete details.
[main] WARN org.springframework.context.annotation.AnnotationConfigApplicationContext - Exception encountered during context initialization - cancelling refresh attempt
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'CsvReader' defined in batch.spring.example.job.ImportDataJob: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.batch.item.ItemReader]: Factory method 'CsvReader' threw exception; nested exception is java.lang.NullPointerException
  at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:599)
  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1123)
  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1018)
  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510)
  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
  at org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:305)
  at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
  at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:301)
  at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196)
  at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772)
  at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)
  at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
  at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:84)
  at batch.spring.example.ImportDataApp.main(ImportDataApp.java:24)
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.batch.item.ItemReader]: Factory method 'CsvReader' threw exception; nested exception is java.lang.NullPointerException
  at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:189)
  at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588)
  ... 13 more
Caused by: java.lang.NullPointerException
  at batch.spring.example.job.item_reader.CsvReader.<init>(CsvReader.java:28)
  at batch.spring.example.job.ImportDataJob.CsvReader(ImportDataJob.java:67)
  at batch.spring.example.job.ImportDataJob$$EnhancerBySpringCGLIB$$eb882444.CGLIB$CsvReader(<generated>)
  at batch.spring.example.job.ImportDataJob$$EnhancerBySpringCGLIB$$eb882444$$FastClassBySpringCGLIB$d548885.invoke(<generated>)
  at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
  at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:309)
  at batch.spring.example.job.ImportDataJob$$EnhancerBySpringCGLIB$$eb882444.CsvReader(<generated>)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.lang.reflect.Method.invoke(Method.java:497)
  at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162)
  ... 14 more
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'CsvReader' defined in batch.spring.example.job.ImportDataJob: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.batch.item.ItemReader]: Factory method 'CsvReader' threw exception; nested exception is java.lang.NullPointerException
  at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:599)
  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1123)
  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1018)
  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510)
  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
  at org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:305)
  at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
  at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:301)
  at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196)
  at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772)
  at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)
  at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
  at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:84)
  at batch.spring.example.ImportDataApp.main(ImportDataApp.java:24)
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.batch.item.ItemReader]: Factory method 'CsvReader' threw exception; nested exception is java.lang.NullPointerException
  at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:189)
  at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588)
  ... 13 more
Caused by: java.lang.NullPointerException
  at batch.spring.example.job.item_reader.CsvReader.<init>(CsvReader.java:28)
  at batch.spring.example.job.ImportDataJob.CsvReader(ImportDataJob.java:67)
  at batch.spring.example.job.ImportDataJob$$EnhancerBySpringCGLIB$$eb882444.CGLIB$CsvReader(<generated>)
  at batch.spring.example.job.ImportDataJob$$EnhancerBySpringCGLIB$$eb882444$$FastClassBySpringCGLIB$d548885.invoke(<generated>)
  at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
  at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:309)
  at batch.spring.example.job.ImportDataJob$$EnhancerBySpringCGLIB$$eb882444.CsvReader(<generated>)
  at sun.reflect.NativeMethodAccessorImpl.inv    [main] INFO org.springframework.context.annotation.AnnotationConfigApplicationContext - Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@5c29bfd: startup date [Thu Oct 22 11:26:18 IST 2015]; root of context hierarchy
[main] INFO org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader - Skipping bean definition for [BeanMethod:name=importDataJob,declaringClass=batch.spring.example.job.ImportDataJob]: a definition for bean 'importDataJob' already exists. This top-level bean definition is considered as an override.
[main] WARN org.springframework.context.annotation.ConfigurationClassEnhancer - @Bean method ScopeConfiguration.stepScope is non-static and returns an object assignable to Spring's BeanFactoryPostProcessor interface. This will result in a failure to process annotations such as @Autowired, @Resource and @PostConstruct within the method's declaring @Configuration class. Add the 'static' modifier to this method to avoid these container lifecycle issues; see @Bean javadoc for complete details.
[main] WARN org.springframework.context.annotation.ConfigurationClassEnhancer - @Bean method ScopeConfiguration.jobScope is non-static and returns an object assignable to Spring's BeanFactoryPostProcessor interface. This will result in a failure to process annotations such as @Autowired, @Resource and @PostConstruct within the method's declaring @Configuration class. Add the 'static' modifier to this method to avoid these container lifecycle issues; see @Bean javadoc for complete details.
[main] WARN org.springframework.context.annotation.AnnotationConfigApplicationContext - Exception encountered during context initialization - cancelling refresh attempt
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'CsvReader' defined in batch.spring.example.job.ImportDataJob: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.batch.item.ItemReader]: Factory method 'CsvReader' threw exception; nested exception is java.lang.NullPointerException
  at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:599)
  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1123)
  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1018)
  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510)
  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
  at org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:305)
  at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
  at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:301)
  at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196)
  at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772)
  at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)
  at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
  at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:84)
  at batch.spring.example.ImportDataApp.main(ImportDataApp.java:24)
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.batch.item.ItemReader]: Factory method 'CsvReader' threw exception; nested exception is java.lang.NullPointerException
  at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:189)
  at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588)
  ... 13 more
Caused by: java.lang.NullPointerException
  at batch.spring.example.job.item_reader.CsvReader.<init>(CsvReader.java:28)
  at batch.spring.example.job.ImportDataJob.CsvReader(ImportDataJob.java:67)
  at batch.spring.example.job.ImportDataJob$$EnhancerBySpringCGLIB$$eb882444.CGLIB$CsvReader(<generated>)
  at batch.spring.example.job.ImportDataJob$$EnhancerBySpringCGLIB$$eb882444$$FastClassBySpringCGLIB$d548885.invoke(<generated>)
  at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
  at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:309)
  at batch.spring.example.job.ImportDataJob$$EnhancerBySpringCGLIB$$eb882444.CsvReader(<generated>)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.lang.reflect.Method.invoke(Method.java:497)
  at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162)
  ... 14 more
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'CsvReader' defined in batch.spring.example.job.ImportDataJob: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.batch.item.ItemReader]: Factory method 'CsvReader' threw exception; nested exception is java.lang.NullPointerException
  at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:599)
  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1123)
  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1018)
  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510)
  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
  at org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:305)
  at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
  at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:301)
  at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196)
  at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772)
  at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)
  at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
  at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:84)
  at batch.spring.example.ImportDataApp.main(ImportDataApp.java:24)
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.batch.item.ItemReader]: Factory method 'CsvReader' threw exception; nested exception is java.lang.NullPointerException
  at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:189)
  at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588)
  ... 13 more
Caused by: java.lang.NullPointerException
  at batch.spring.example.job.item_reader.CsvReader.<init>(CsvReader.java:28)
  at batch.spring.example.job.ImportDataJob.CsvReader(ImportDataJob.java:67)
  at batch.spring.example.job.ImportDataJob$$EnhancerBySpringCGLIB$$eb882444.CGLIB$CsvReader(<generated>)
  at batch.spring.example.job.ImportDataJob$$EnhancerBySpringCGLIB$$eb882444$$FastClassBySpringCGLIB$d548885.invoke(<generated>)
  at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
  at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:309)
  at batch.spring.example.job.ImportDataJob$$EnhancerBySpringCGLIB$$eb882444.CsvReader(<generated>)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.lang.reflect.Method.invoke(Method.java:497)
  at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162)
  ... 14 more

这一切都归结为对象的构造和自动装配方式。要构造一个对象,必须调用构造函数。然后你有一个对象的引用,并且可以设置它的字段。这就是 Spring 在创建 bean 并自动装配它们时所做的:它调用构造函数,然后设置所有用 @Autowired 注释的字段。它不能在调用构造函数之前设置字段,因为它还没有任何对象。

但是您的构造函数甚至在构造对象之前就试图访问本应由 Spring 自动装配的字段。这不可能发生。

要从构造函数访问自动装配的 bean,必须使用构造函数注入。另一种选择是将所有这些代码从构造函数移动到用 @PostConstruct.

注释的方法