具有AnnotationConfigApplicationContext的Spring应用程序:获取运行时异常

时间:2019-06-02 13:29:24

标签: java spring spring-ioc

这是我的一个SO问题的延续-> here

我扩展了相同的示例,并且希望能“很好”地工作,但是我遇到了NullPointerException。

这是完整的源代码:

FirstBean.java

$id = R::store($site);

SomeBean.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 + "]";
    }
}

MainDriver.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");
    }
}

我期望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(); } } 得到SomeBeanAutowiredctxenv的Autowired效果很好),但没有得到,我是出现运行时异常。

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$0(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$0(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,但仍然会出现异常。

任何人都可以帮助我在理解上滞后的地方以及如何解决它。

1 个答案:

答案 0 :(得分:1)

我认为这是因为Spring首先必须实例化您的SomeBean类,然后它会尝试通过反射自动装配FirstBean,因为您在字段上放置了@Autowired注释。

您正在尝试访问FirstBean构造函数中的SomeBean依赖项,但是当调用SomeBean的构造函数时,在创建上下文时,FirstBean依赖项为null,因为Spring尚未自动装配依赖关系-在创建对象之后,它将尝试通过反射对其自动装配。这就是为什么在那里到达NullPointerException的原因。您的SomeBean类也会遇到相同的情况-选择一种方法。

此外,您创建同时用@Configuration@Component注释的类很奇怪。请参阅this SO question以查看潜在的错误。

此外,您的配置中存在一些问题。您用FirstBean注释了@Component,但仍然创建了一个@Bean注释的方法,该方法返回该类的实例。您应该确定一个方法-使用@Bean注释为应用程序实例化它,或者使用@Component注释该类,然后让组件扫描自动为您创建它。

编辑

您应该决定是要使用@ComponentScan还是要通过@Bean批注为上下文创建bean-现在,您正在混合使用不同的类型,并且当重复的bean定义出现错误时尝试按类型自动装配,因为在您的上下文中,当前的实现中有SomeBean有2个bean和FirstBean有2个bean-它们将只有不同的ID。请注意,我指出的与NPE期望有关的错误与它无关。我将提出一种使用自动包裹扫描的解决方案:

FirstBean类

@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 + "]";
    }
}

SomeBean类

@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();
    }
}

MyConfig类

@Configuration
@ComponentScan(basePackages = { "com.example" })
public class MyConfig {

}

MainDriver类

@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();
    }
}