[英]Unable to get Autowired to work or do a component scan
I'm using Spring for the first time and even though I feel like I'm familiar with the core IoC concept, I'm having trouble getting the @Autowired configuration working. 我是第一次使用Spring,即使我觉得自己熟悉核心IoC概念,也无法使@Autowired配置正常工作。 I've created this github to demonstrate (stack: basic service using Jersey/Tomcat/Spring/Maven): 我创建了这个github进行演示(堆栈:使用Jersey / Tomcat / Spring / Maven的基本服务):
https://github.com/dkwestbr/autowired_example https://github.com/dkwestbr/autowired_example
I'm not using any sort of xml configuration (either for Spring or Tomcat). 我没有使用任何类型的xml配置(用于Spring或Tomcat)。 I can start the server and map to my Jersey end point successfully using mvn clean tomcat7:run
but my service is hitting a NullPointerException because the object I'm trying to Autowire isn't being initialized by the Spring framework. 我可以使用mvn clean tomcat7:run
启动服务器并成功映射到我的Jersey端点,但是我的服务遇到NullPointerException mvn clean tomcat7:run
因为Spring框架没有初始化我尝试自动mvn clean tomcat7:run
的对象。
Here is the break down of my current makeup: 这是我目前的妆容分解图:
Why isn't spring detecting/initializing my autowired variable? 为什么不弹簧检测/初始化我的自动接线变量? I've been reading through tutorials for a while now and am at my wits end. 我已经阅读了一段时间的教程,并且精疲力尽。 It doesn't help that most tutorials are written using xml configurations. 大多数教程都是使用xml配置编写的,这无济于事。
Below are the specific code snippets which I'm referencing above: 以下是我上面引用的特定代码段:
The class with the variable I'm trying to initialize via the @Autowired
annotation: 我尝试通过@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());
}
}
My config: 我的配置:
@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 { }
}
Where the config is being loaded: 加载配置的位置:
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, "/*");
}
}
The @Configuration
/ Bean
definition that I'm hoping would map to the @Autowired
variable: 我希望将@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 : I'm providing the stack trace on request (This is line 20: System.out.println(getTheThing.getItGood());
).... 更新 :我应要求提供堆栈跟踪(这是第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)
Taking a quick look at your classes, it seems to me like you aren't integrating Spring with Jersey. 快速浏览一下您的课程,在我看来,您似乎没有将Spring和Jersey集成在一起。 The ServletContainer
will scan and create its own instance of your WebEndpoint
class, but it has no knowledge of the Spring context available in the ServletContext
. ServletContainer
将扫描并创建自己的WebEndpoint
类实例,但是不了解ServletContext
中可用的Spring上下文。
For complete Spring-Jersey integration, take a look at this tutorial . 要完全实现Spring-Jersey集成,请看一下本教程 。 You will need to switch to SpringServlet
and add a new library that binds the two. 您将需要切换到SpringServlet
并添加一个将两者绑定在一起的新库。
As for your configuration, the @Bean
annotation only makes sense in the context of a @Configuration
annotated class. 对于您的配置, @Bean
批注仅在带有@Configuration
批注的类的上下文中才有意义。 This doesn't make any sense 这没有任何意义
@Component
public class A implements IStringGetter {
@Bean
public IStringGetter getTheThing() {
return new A();
}
@Override
public String getItGood() {
return "I am an A";
}
}
Get rid of the @Bean
method. 摆脱@Bean
方法。 With a @ComponentScan
, @Component
annotated classes will be instantiated and the bean will be added to the context. 使用@ComponentScan
,将实例化@Component
注释的类,并将Bean添加到上下文中。 Also changed your AppConfig
@ComponentScan
to @ComponentScan
您的AppConfig
@ComponentScan
更改为
@ComponentScan(basePackages = {"dkwestbr.spring.autowired.example"})
It recurs through that package. 它通过该包重复出现。
Your two nested @Configuration
classes also serve no purpose as it stands. 您的两个嵌套@Configuration
类也没有任何作用。
For beans not managed by Spring use extends SpringBeanAutowiringSupport
and it should work. 对于不是由Spring管理的bean,请使用extends SpringBeanAutowiringSupport
,它应该可以工作。 In the above example make class WebEndpoint
extend SpringBeanAutowiringSupport
在上面的示例中,使类WebEndpoint
扩展SpringBeanAutowiringSupport
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.