Spring Context init(java) [英] Spring Context init (java)
问题描述
我是春天的初学者,我遇到了基本的上下文初始化问题,我找不到任何简单的教程。
所以我想做的是基本的依赖注入,我已经看到我只需要将类标记为@Componant或@Service,并使用@Autowired直接将它们注入目标文件中。
为此,我需要正确设置我的spring上下文(我需要构建一个Web服务+使用JPA,所以我想构建一个webapp)
I'm a beginner with spring and I am having problem with basic context init and I can't find any easy tutorial. So what I want to do is basic dependency injection and I have seen I only have to mark classes as @Componant or @Service and inject them directly within target fiels with @Autowired. For this I need to set properly my spring context (I'll need to build a web service + use JPA so I want to build a webapp)
我正在使用JDK 1.8,maven 3.2.1
I'm using JDK 1.8, maven 3.2.1
我想做一个基本的依赖注入。
=>我想在那里注入一个storeImpl实例,但这会导致空指针异常
=>这项工作完全没有注入(私有商店storeImpl = new storeImpl();)
I want to do a basic dependency injection. => I want to inject a storeImpl instance there but this lead to a null pointer exception => this work perfectly without injection ( private Store storeImpl = new storeImpl(); )
package com.mycompany.app.controller;
@Controller
public class Controller
{
@Autowired
private Store storeImpl;
public void use()
{
storeImpl.get();
}
}
package com.mycompany.app.store;
public interface Store {
boolean get();
}
package com.mycompany.app.store;
@Component
public class StoreImpl implements Store {
@Override
public boolean get()
{
return true;
}
}
=>我的主要(我测试我的适用于此的应用程序):
public class App
{
public static void main(String[] args)
{
Controller controller = new Controller();
controller.use();
}
}
=>我的pom.xml
=> my pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>my-app</name>
<url>http://maven.apache.org</url>
<properties>
<spring.version>4.0.4.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.7.1</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.12.6</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.5.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.3.5.Final</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
=>我的web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/META-INF/spring-context.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
</web-app>
=>我的spring-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--<context:component-scan base-package="com.mycompany.app"/>-->
<context:component-scan base-package="com.mycompany.app">
<!-- <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />-->
</context:component-scan>
</beans>
=>我的项目架构
my-app
src
main
java
com.mycompagny.app
controller
Controller.java
store
Store.java
StoreImpl.java
app.java
ressources
META-INF
spring-context.xml
webapp
WEB-INF
web.xml
test
java
pom.xml
=> main()的堆栈跟踪
=> stacktrace of main()
Exception in thread "main" java.lang.NullPointerException
at com.mycompany.app.controller.Controller.run(Controller.java:25)
at com.mycompany.app.App.main(App.java:19)
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:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
所以我的问题是我的注入字段(storeImpl)为null。
我想我错过了一些关于context init的东西?
再次感谢您的帮助和您的回答
So my problem is my injected field (storeImpl) is null. And I think I miss something with context init ? Thanks again for your help and yourr grats answer
推荐答案
您有几个问题(以下内容显而易见:你的帖子)。
You have a couple of problems (the following are apparent from your post).
- 混合不同版本的Spring的罐子
- 注释的错误位置
- applicationcontext中的重复。
- 使用版本化的XSD文件。
- web.xml中的版本冲突
- Mixing jars of different versions of Spring
- Wrong location of annotations
- Duplication in your applicationcontext.
- Using versioned XSD files.
- Conflicting versioning in web.xml
1。混合不同版本的Spring的罐子
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.0.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.0.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.0.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.0.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.0.1.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>3.0.5.RELEASE</version>
</dependency>
您的pom上堆满了来自不同弹簧版本的罐子(3.0.5,4.0.1,4.0。 3和4.0.3)。如果你想要麻烦,那么这就是你要走的路。始终坚持单一版本的框架,不要混合来自不同版本的罐子。这不仅适用于Spring,而是适用于每个(多jar)框架。
Your pom is littered with jars from different spring versions (3.0.5, 4.0.1, 4.0.3 and 4.0.3). If you want trouble then that is the way to go. Always stick to a single version of a framework and don't mix jars from different versions. This isn't only for Spring but goes for every (multi jar) framework out-there.
使用maven的强大功能来帮助你,指定一个属性来保存你想要使用的Spring版本并使用该属性。
Use the power of maven to help you, specify a property to hold the version of Spring you want to use and use that property.
<properties>
<spring.version>4.0.4.RELEASE</spring.version>
</properties>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
您可能需要添加更多内容,具体取决于Spring Data JPA引入的依赖项,如果是有不同的版本。
You might need to add a couple more depending on which dependencies Spring Data JPA is pulling in, if that has different versions.
2。注释的位置错误
@Service
public interface Store {
boolean get();
}
注释不是从接口继承的,所以在界面上添加注释很漂亮没用。对于特定的注释,例如 @Transactional
,Spring有一些hacks,但不适用于此。将注释移动到具体实现,不要将其放在界面上。
Annotations aren't inherited from interfaces so putting the annotation on the interface is pretty much useless. Spring has some hacks in place for specific annotations like @Transactional
but not for this. Move the annotation to the concrete implementation and don't put it on the interface.
@Service
public class Controller {
@Autowired
private Store storeImpl;
public void use() {
storeImpl.get();
}
}
我在这里看不到任何东西 @Controller
或者什么也没有 @RequestMapping
所以我不确定你认为Spring如何检测和处理这个类。
I don't see anything here no @Controller
or what so ever also no @RequestMapping
so I'm not sure how you think that Spring detects and handles this class.
3。在applicationcontext中重复。
< context:annotation-config />
将其从使用< context:component-scan />
已经隐含了您的上下文。
<context:annotation-config />
remove it from your context as that is already implied by the use of <context:component-scan />
.
< mvc:annotation-driven />
应仅在<$加载的xml文件中c $ c> DispatcherServlet 在你的情况下(如果你已发布实际代码)应该是 dispatcher-servlet.xml
。
<mvc:annotation-driven />
should be only in the xml file loaded by the DispatcherServlet
in your case (if you have posted actual code) that should be the dispatcher-servlet.xml
.
您的xml文件中都有相同的< context:component-scan .. />
元素,这将导致bean重复。由 ContextLoaderListener
加载的文件应该加载除 @Controllers
和 DispatcherServlet $之外的任何文件c $ c>应仅加载
@Controllers
并忽略其他任何内容。要在组件扫描时使用包含/排除过滤器。
You have the same <context:component-scan .. />
element in both your xml files, this will ead to bean duplication. The files loaded by the ContextLoaderListener
should load anything but @Controllers
and the DispatcherServlet
should load only @Controllers
and ignore anything else. To accomplish that use include/exclude filters when component scanning.
将此用于 ContextLoaderListener
。
<context:component-scan base-package="com.mycompany.app">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype. Controller" />
<context:component-scan>
将此用于 DispatcherServlet
。
<context:component-scan base-package="com.mycompany.app" use-default-filters="false >
<context:include-filter type="annotation" expression="org.springframework.stereotype. Controller" />
<context:component-scan>
也不要将 DispatcherServlet
的配置导入 ContextLoaderListener
,因为这将再次导致bean重复。
Also don't import the configuration of the DispatcherServlet
into the ContextLoaderListener
as this will again lead to bean duplication.
4.使用版本化的XSD文件。
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
您的架构位置使用版本化的XSD文件,建议使用无版本的xsd文件。这将确保将加载属于您当前版本的xsd版本。
Your schema locations use versioned XSD files, it is recommended to use versionless xsd files. This will ensure that the xsd version belonging to your current spring version will be loaded.
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
5。 web.xml中的版本控制冲突
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
你想要什么版本2.3的2.4?你在你的pom中包括servlet-api 2.5,我希望你想要3.0版本。相应地更改标题(和maven依赖关系)。
What is it you want version 2.3 of 2.4? You including servlet-api 2.5 in your pom and I would expect that you want version 3.0. Change your header (and maven dependency) accordingly.
将 web.xml
标题更改为以下内容。
Change your web.xml
header to the following.
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
更新你的pom.xml以包含servlet 3.0规范。
Update your pom.xml to include the servlet 3.0 spec.
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
这篇关于Spring Context init(java)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!