无法使Autowired工作或进行组件扫描

时间:2013-10-10 17:33:21

标签: java spring maven inversion-of-control autowired

我第一次使用Spring,尽管我觉得我熟悉IoC的核心概念,但我无法让@Autowired配置正常工作。我已经创建了这个github来演示(stack:使用Jersey / Tomcat / Spring / Maven的基本服务):

https://github.com/dkwestbr/autowired_example

我没有使用任何类型的xml配置(对于Spring或Tomcat)。我可以使用mvn clean tomcat7:run启动服务器并成功映射到我的Jersey端点,但是我的服务遇到了NullPointerException,因为我正在尝试自动装配的对象没有被Spring框架初始化。

以下是我目前化妆的细分:

为什么弹簧检测/初始化我的自动装配变量?我已经阅读了一段时间的教程并且在我的智慧结束时。大多数教程都是使用xml配置编写的,这无济于事。


以下是我上面提到的具体代码段:

具有变量的类我试图通过@Autowired注释初始化:

@Path("/foo")
public class WebEndpoint {

    @Autowired
    private IStringGetter getTheThing;

    @GET
    @Path("/bar")
    @Produces(MediaType.TEXT_HTML)
    public String getStuff() {
        System.out.println(getTheThing.getItGood());
        return String.format("<html><body>Hello - %s</body></html>", getTheThing.getItGood());
    }
}

我的配置:

@Configuration
@ComponentScan(basePackages = {"dkwestbr.spring.autowired.example.**"})
public class AppConfig {

    @Bean
    private static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }

    @Configuration
    @PropertySource("classpath:configuration.properties")
    static class Production { }

    @Configuration
    @Profile("test")
    @PropertySource("classpath:configuration.properties")
    static class Test { }
}

正在加载配置:

public class Initializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext context) throws ServletException {
        AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext();
        appContext.register(AppConfig.class);
        context.addListener(new ContextLoaderListener(appContext));

        Map<String, String> filterParameters = new HashMap<>();

        // set filter parameters
        filterParameters.put("com.sun.jersey.config.property.packages", "dkwestbr.spring.autowired.example");
        filterParameters.put("com.sun.jersey.config.property.JSPTemplatesBasePath", "/WEB-INF/app");
        filterParameters.put("com.sun.jersey.config.property.WebPageContentRegex", "/(images|css|jsp)/.*");

        // register filter
        FilterRegistration.Dynamic filterDispatcher = context.addFilter("webFilter", new ServletContainer());
        filterDispatcher.setInitParameters(filterParameters);
        filterDispatcher.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), false, "/*");
    }

}

我希望将@Configuration / Bean定义映射到@Autowired变量:

@Component
public class A implements IStringGetter {

    @Bean
    public IStringGetter getTheThing() {
        return new A();
    }

    @Override
    public String getItGood() {
        return "I am an A";
    }

}

UPDATE :我正在提供请求的堆栈跟踪(这是第20行:System.out.println(getTheThing.getItGood());)....

java.lang.NullPointerException
    dkwestbr.spring.autowired.example.WebEndpoint.getStuff(WebEndpoint.java:20)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    java.lang.reflect.Method.invoke(Method.java:606)
    com.sun.jersey.spi.container.JavaMethodInvokerFactory$1.invoke(JavaMethodInvokerFactory.java:60)
    com.sun.jersey.server.impl.model.method.dispatch.AbstractResourceMethodDispatchProvider$TypeOutInvoker._dispatch(AbstractResourceMethodDispatchProvider.java:185)
    com.sun.jersey.server.impl.model.method.dispatch.ResourceJavaMethodDispatcher.dispatch(ResourceJavaMethodDispatcher.java:75)
    com.sun.jersey.server.impl.uri.rules.HttpMethodRule.accept(HttpMethodRule.java:288)
    com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:147)
    com.sun.jersey.server.impl.uri.rules.ResourceClassRule.accept(ResourceClassRule.java:108)
    com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:147)
    com.sun.jersey.server.impl.uri.rules.RootResourceClassesRule.accept(RootResourceClassesRule.java:84)
    com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1469)
    com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1400)
    com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1349)
    com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1339)
    com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:416)
    com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:537)
    com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:699)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:728)

2 个答案:

答案 0 :(得分:3)

快速浏览一下你的课程,我觉得你并没有把Spring和Jersey整合在一起。 ServletContainer将扫描并创建自己的WebEndpoint类实例,但它不了解ServletContext中可用的Spring上下文。

要完成Spring-Jersey集成,请查看this tutorial。您需要切换到SpringServlet并添加一个绑定两者的新库。


对于您的配置,@Bean注释仅在@Configuration带注释的类的上下文中有意义。这没有任何意义

@Component
public class A implements IStringGetter {    
    @Bean
    public IStringGetter getTheThing() {
        return new A();
    }    
    @Override
    public String getItGood() {
        return "I am an A";
    }    
}

摆脱@Bean方法。使用@ComponentScan,将实例化@Component带注释的类,并将bean添加到上下文中。同时将您的AppConfig @ComponentScan更改为

@ComponentScan(basePackages = {"dkwestbr.spring.autowired.example"})

它通过该包重复出现。

您的两个嵌套@Configuration类也没有任何目的。

答案 1 :(得分:1)

对于不由Spring管理的bean使用extends SpringBeanAutowiringSupport,它应该可以工作。 在上面的示例中,make class WebEndpoint扩展为SpringBeanAutowiringSupport