Spring 具有 AnnotationConfigApplicationContext 的应用程序:出现 运行 时间异常
Spring application having AnnotationConfigApplicationContext: getting run time exception
这是我的一个 SO 问题的延续 -->
我扩展了相同的示例,我希望可以工作 "just fine",但是我收到 NullPointerException。
这里是完整的源代码:
FirstBean.java
package com.example;
import org.springframework.stereotype.Component;
@Component
public class FirstBean {
public FirstBean() {
}
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "FirstBean [name=" + name + "]";
}
}
SomeBean.java
package com.example;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
@Component
@Configuration
@ComponentScan(basePackages = { "com.example" })
public class SomeBean {
@Autowired
private FirstBean fb;
@Bean
FirstBean instantiateFirstBean() {
return new FirstBean();
}
public SomeBean() {
// this.fb.setName("Some Name"); -> this was causing problem as
// bean isn't still created fully
}
public void print() {
this.fb.toString();
}
@PostConstruct
void post() {
fb.setName("Some name");
}
}
MainDriver.java
package com.example;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
@Configuration
@ComponentScan(basePackages = { "com.example" })
@PropertySource(ignoreResourceNotFound = true, value = "classpath:/application.props")
public class MainDriver {
@Autowired
private Environment env;
@Autowired
private ConfigurableEnvironment cenv;
@Autowired
ApplicationContext ctx;
@Autowired
private SomeBean sb;
@Bean
public SomeBean instantiateSomeBean() {
return new SomeBean();
}
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(MainDriver.class);
MainDriver l = ctx.getBean(MainDriver.class);
System.out.println("In main() the ctx is " + ctx);
l.test();
}
public void test() {
System.out.println("hello");
sb.print();
}
}
我期待 SomeBean
得到 Autowired
(ctx
、env
、cenv
正在完美地自动装配),但它没有得到并且我收到 运行 时间异常。
Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'mainDriver': Unsatisfied dependency expressed through field 'sb'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'someBean' defined in file [/Users/vkoul/understand-code/platform/stream-base/trunk/target/classes/com/example/SomeBean.class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.example.SomeBean$$EnhancerBySpringCGLIB$$fad3571b]: Constructor threw exception; nested exception is java.lang.NullPointerException
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'mainDriver': Unsatisfied dependency expressed through field 'sb'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'someBean' defined in file [/Users/vkoul/understand-code/platform/stream-base/trunk/target/classes/com/example/SomeBean.class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.example.SomeBean$$EnhancerBySpringCGLIB$$fad3571b]: Constructor threw exception; nested exception is java.lang.NullPointerException
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:584)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:370)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1336)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:572)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:495)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean[=15=](AbstractBeanFactory.java:317)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:759)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:548)
at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:88)
at com.example.MainDriver.main(MainDriver.java:37)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'someBean' defined in file [/Users/vkoul/understand-code/platform/stream-base/trunk/target/classes/com/example/SomeBean.class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.example.SomeBean$$EnhancerBySpringCGLIB$$fad3571b]: Constructor threw exception; nested exception is java.lang.NullPointerException
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1228)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1127)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:535)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:495)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean[=15=](AbstractBeanFactory.java:317)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:251)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1135)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1062)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:581)
... 14 more
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.example.SomeBean$$EnhancerBySpringCGLIB$$fad3571b]: Constructor threw exception; nested exception is java.lang.NullPointerException
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:182)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:87)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1220)
... 25 more
Caused by: java.lang.NullPointerException
at com.example.SomeBean.<init>(SomeBean.java:23)
at com.example.SomeBean$$EnhancerBySpringCGLIB$$fad3571b.<init>(<generated>)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:170)
... 27 more
我也提到了 @Bean
,我希望它能告诉我们如何创建这些 bean,但仍然遇到异常。
任何人都可以帮助我了解滞后的地方以及如何解决它。
我认为这是因为 Spring 将首先必须实例化您的 SomeBean
class 然后它将尝试通过反射自动装配 FirstBean
因为您将 @Autowired
字段注释。
您正在尝试访问 SomeBean
构造函数中的 FirstBean
依赖项,但是当调用 SomeBean
的构造函数时,在创建上下文时,FirstBean
依赖项为空因为 Spring 还没有自动装配依赖 - 它会在对象创建后尝试通过反射自动装配它。这就是为什么你在那里得到 NullPointerException
。同样的情况发生在你的 SomeBean
class - 决定一种方法。
此外,您创建的 class 都带有 @Configuration
和 @Component
注释,这很奇怪。请参考 this SO question 查看潜在的错误。
此外,您的配置存在一些问题。您使用 @Component
注释对 FirstBean
进行注释,并且您仍然创建了一个 @Bean
注释方法,该方法 returns 此 class 的实例。你应该决定一个方法 - 你使用 @Bean
注释为应用程序上下文实例化它,或者你用 @Component
注释这个 class 然后让组件扫描自动为你创建它。
编辑:
您应该决定是要使用 @ComponentScan
还是要通过 @Bean
注释为上下文创建 bean - 现在您正在混合不同的类型,并且您将得到重复 bean 的错误尝试按类型自动装配时的定义,因为在您当前的实现中,在您的上下文中将有 2 个用于 SomeBean
的 bean 和 2 个用于 FirstBean
的 bean - 它们将只有不同的 ID。请注意,我用 NPE 期望指出的错误与它无关。我将提出一个使用自动包扫描的解决方案:
FirstBean class
@Component
public class FirstBean {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "FirstBean [name=" + name + "]";
}
}
SomeBeanclass
@Component
public class SomeBean {
private FirstBean fb;
@Autowired
public SomeBean(FirstBean firstBean) {
this.fb = firstBean;
this.fb.setName("Some Name");
}
public void print() {
this.fb.toString();
}
}
我的配置class
@Configuration
@ComponentScan(basePackages = { "com.example" })
public class MyConfig {
}
主驱动class
@Component
public class MainDriver {
@Autowired
private Environment env;
@Autowired
protected ConfigurableEnvironment cenv;
@Autowired
ApplicationContext ctx;
@Autowired
private SomeBean sb;
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(MyConfig.class);
MainDriver l = ctx.getBean(MainDriver.class);
System.out.println("In main() the ctx is " + ctx);
l.test();
}
public void test() {
System.out.println("hello");
sb.print();
}
}
这是我的一个 SO 问题的延续 -->
我扩展了相同的示例,我希望可以工作 "just fine",但是我收到 NullPointerException。
这里是完整的源代码:
FirstBean.java
package com.example;
import org.springframework.stereotype.Component;
@Component
public class FirstBean {
public FirstBean() {
}
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "FirstBean [name=" + name + "]";
}
}
SomeBean.java
package com.example;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
@Component
@Configuration
@ComponentScan(basePackages = { "com.example" })
public class SomeBean {
@Autowired
private FirstBean fb;
@Bean
FirstBean instantiateFirstBean() {
return new FirstBean();
}
public SomeBean() {
// this.fb.setName("Some Name"); -> this was causing problem as
// bean isn't still created fully
}
public void print() {
this.fb.toString();
}
@PostConstruct
void post() {
fb.setName("Some name");
}
}
MainDriver.java
package com.example;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
@Configuration
@ComponentScan(basePackages = { "com.example" })
@PropertySource(ignoreResourceNotFound = true, value = "classpath:/application.props")
public class MainDriver {
@Autowired
private Environment env;
@Autowired
private ConfigurableEnvironment cenv;
@Autowired
ApplicationContext ctx;
@Autowired
private SomeBean sb;
@Bean
public SomeBean instantiateSomeBean() {
return new SomeBean();
}
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(MainDriver.class);
MainDriver l = ctx.getBean(MainDriver.class);
System.out.println("In main() the ctx is " + ctx);
l.test();
}
public void test() {
System.out.println("hello");
sb.print();
}
}
我期待 SomeBean
得到 Autowired
(ctx
、env
、cenv
正在完美地自动装配),但它没有得到并且我收到 运行 时间异常。
Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'mainDriver': Unsatisfied dependency expressed through field 'sb'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'someBean' defined in file [/Users/vkoul/understand-code/platform/stream-base/trunk/target/classes/com/example/SomeBean.class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.example.SomeBean$$EnhancerBySpringCGLIB$$fad3571b]: Constructor threw exception; nested exception is java.lang.NullPointerException
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'mainDriver': Unsatisfied dependency expressed through field 'sb'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'someBean' defined in file [/Users/vkoul/understand-code/platform/stream-base/trunk/target/classes/com/example/SomeBean.class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.example.SomeBean$$EnhancerBySpringCGLIB$$fad3571b]: Constructor threw exception; nested exception is java.lang.NullPointerException
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:584)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:370)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1336)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:572)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:495)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean[=15=](AbstractBeanFactory.java:317)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:759)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:548)
at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:88)
at com.example.MainDriver.main(MainDriver.java:37)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'someBean' defined in file [/Users/vkoul/understand-code/platform/stream-base/trunk/target/classes/com/example/SomeBean.class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.example.SomeBean$$EnhancerBySpringCGLIB$$fad3571b]: Constructor threw exception; nested exception is java.lang.NullPointerException
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1228)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1127)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:535)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:495)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean[=15=](AbstractBeanFactory.java:317)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:251)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1135)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1062)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:581)
... 14 more
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.example.SomeBean$$EnhancerBySpringCGLIB$$fad3571b]: Constructor threw exception; nested exception is java.lang.NullPointerException
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:182)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:87)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1220)
... 25 more
Caused by: java.lang.NullPointerException
at com.example.SomeBean.<init>(SomeBean.java:23)
at com.example.SomeBean$$EnhancerBySpringCGLIB$$fad3571b.<init>(<generated>)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:170)
... 27 more
我也提到了 @Bean
,我希望它能告诉我们如何创建这些 bean,但仍然遇到异常。
任何人都可以帮助我了解滞后的地方以及如何解决它。
我认为这是因为 Spring 将首先必须实例化您的 SomeBean
class 然后它将尝试通过反射自动装配 FirstBean
因为您将 @Autowired
字段注释。
您正在尝试访问 SomeBean
构造函数中的 FirstBean
依赖项,但是当调用 SomeBean
的构造函数时,在创建上下文时,FirstBean
依赖项为空因为 Spring 还没有自动装配依赖 - 它会在对象创建后尝试通过反射自动装配它。这就是为什么你在那里得到 NullPointerException
。同样的情况发生在你的 SomeBean
class - 决定一种方法。
此外,您创建的 class 都带有 @Configuration
和 @Component
注释,这很奇怪。请参考 this SO question 查看潜在的错误。
此外,您的配置存在一些问题。您使用 @Component
注释对 FirstBean
进行注释,并且您仍然创建了一个 @Bean
注释方法,该方法 returns 此 class 的实例。你应该决定一个方法 - 你使用 @Bean
注释为应用程序上下文实例化它,或者你用 @Component
注释这个 class 然后让组件扫描自动为你创建它。
编辑:
您应该决定是要使用 @ComponentScan
还是要通过 @Bean
注释为上下文创建 bean - 现在您正在混合不同的类型,并且您将得到重复 bean 的错误尝试按类型自动装配时的定义,因为在您当前的实现中,在您的上下文中将有 2 个用于 SomeBean
的 bean 和 2 个用于 FirstBean
的 bean - 它们将只有不同的 ID。请注意,我用 NPE 期望指出的错误与它无关。我将提出一个使用自动包扫描的解决方案:
FirstBean class
@Component
public class FirstBean {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "FirstBean [name=" + name + "]";
}
}
SomeBeanclass
@Component
public class SomeBean {
private FirstBean fb;
@Autowired
public SomeBean(FirstBean firstBean) {
this.fb = firstBean;
this.fb.setName("Some Name");
}
public void print() {
this.fb.toString();
}
}
我的配置class
@Configuration
@ComponentScan(basePackages = { "com.example" })
public class MyConfig {
}
主驱动class
@Component
public class MainDriver {
@Autowired
private Environment env;
@Autowired
protected ConfigurableEnvironment cenv;
@Autowired
ApplicationContext ctx;
@Autowired
private SomeBean sb;
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(MyConfig.class);
MainDriver l = ctx.getBean(MainDriver.class);
System.out.println("In main() the ctx is " + ctx);
l.test();
}
public void test() {
System.out.println("hello");
sb.print();
}
}