Spring Context初始化(java)


问题内容

我是spring的初学者,我在基本上下文初始化方面遇到问题,找不到任何简单的教程。所以我想做的是基本的依赖注入,我已经看到只需要将类标记为@Componant或@Service并使用@Autowired直接将它们注入目标文件中。为此,我需要正确设置我的spring上下文(我需要构建一个Web服务+使用JPA,所以我想构建一个Webapp)

我正在使用JDK 1.8,Maven 3.2.1

我想做一个基本的依赖注入。=>我想在那里注入一个storeImpl实例,但这导致空指针异常=>无需注入就可以完美地工作(私有商店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

<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()的堆栈跟踪

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。而且我想我有上下文初始化的东西吗?再次感谢您的帮助,您的回答很高兴


问题答案:

您有几个问题(以下内容从您的帖子中显而易见)。

  1. 混合不同版本的Spring的jar
  2. 注释的位置错误
  3. 在您的应用程序上下文中重复。
  4. 使用版本化的XSD文件。
  5. web.xml中的版本冲突

1.混合不同版本的Spring的Jars

  <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上堆满了来自不同spring版本(3.0.5、4.0.1、4.0.3和4.0.3)的广口瓶。如果您要麻烦,那是要走的路。始终坚持使用单一版本的框架,不要混用不同版本的jar。这不仅适用于Spring,而且适用于所有(多罐)框架。

使用Maven的功能来帮助您,指定一个属性以保存要使用的Spring版本并使用该属性。

<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具有不同的版本,则可能需要添加更多依赖项,具体取决于Spring Data JPA引入的依赖项。

2.注释的位置错误

@Service
public interface Store {
    boolean get();
}

注释不是从接口继承的,因此将注释放在接口上几乎没有用。Spring有一些针对特定注释的技巧,例如@Transactional但不是针对此。将注释移至具体的实现,不要将其放在界面上。

@Service
public class Controller {
    @Autowired
    private Store storeImpl;

    public void use() {
       storeImpl.get();
    }
}

我在这里看不到任何东西,@Controller或者什么也从未看到,@RequestMapping所以我不确定您如何认为Spring检测并处理了此类。

3.在您的应用程序上下文中进行复制。

<context:annotation-config />将其从您的上下文中删除,因为使用已经暗示了这一点<context:component- scan />

<mvc:annotation-driven />应该仅在DispatcherServlet您的情况下(如果您已发布实际代码)由加载的xml文件中,该文件应为dispatcher- servlet.xml

<context:component-scan .. />在两个xml文件中都有相同的元素,这将导致Bean复制。由加载的文件ContextLoaderListener应加载除以外的任何内容@Controllers,而DispatcherServlet应当仅加载@Controllers并且忽略其他任何内容。为此,在组件扫描时使用包含/排除过滤器。

将其用于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复制。

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文件。这将确保将加载属于您当前的Spring版本的xsd版本。

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.4版本2.3?您在pom中包含servlet-api 2.5,我希望您想要版本3.0。相应地更改标头(和Maven依赖项)。

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">

更新您的pom.xml以包含Servlet 3.0规范。

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.0.1</version>
    <scope>provided</scope>
</dependency>