【问题标题】:Spring Context init (java)Spring 上下文初始化 (java)
【发布时间】:2014-06-25 16:14:29
【问题描述】:

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

我使用的是 JDK 1.8,maven 3.2.1

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

<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) 为空。 而且我想我错过了 context init 的一些东西? 再次感谢您的帮助,感谢您的回答

【问题讨论】:

  • 到底是什么问题?
  • 在spring xml中为你的实现类定义一个bean
  • 我的问题是我注入的字段 (storeImpl) 为空。我认为 context.xml 从未初始化。我认为使用注释驱动我不需要在 context.xml 中标记 bean 吗?即使我这样做了,该字段仍然为空:s
  • 你的问题太冗长了。不过提示很少:只有 Spring bean 可以将其他 Spring bean 注入其中。您的控制器未使用 Sprig 组件注释进行注释。接口不应使用组件注释进行注释。他们的实施应该是。并且注入的字段(store)的类型应该是接口的类型,而不是实现的类型。所以应该是Store,而不是StoreImpl。我也不明白你为什么在两个 xml 文件中重复相同的配置(以及为什么你首先有 2 个)。
  • 您正在使用组件扫描,所以不要在上下文中定义 bean。这又会导致 bean 重复。目前,由于您帖子的长度和编辑,我对您拥有的内容以及为什么它不起作用感到非常迷茫。请用你现在拥有的代码重写你的帖子,我迷路了。

标签: java spring spring-mvc servlets dependency-injection


【解决方案1】:

你必须在你的 Spring xml 中定义 bean

<bean id="storeImpl" class="com.mycompany.app.store.StoreImpl">
       <!-- collaborators and configuration for this bean go here -->
</bean>

所以,@Autowired bean 将被 Spring 框架注入

【讨论】:

    【解决方案2】:

    您有几个问题(从您的帖子中可以明显看出以下问题)。

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

    1.混合不同版本Spring的jar

      <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,而且适用于所有(多 jar)框架。

    使用 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 引入的依赖项,如果版本不同,您可能需要添加更多。

    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.应用程序上下文中的重复。

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

    &lt;mvc:annotation-driven /&gt; 应该只在您的情况下由DispatcherServlet 加载的xml 文件中(如果您发布了实际代码),应该是dispatcher-servlet.xml

    您的两个 xml 文件中有相同的 &lt;context:component-scan .. /&gt; 元素,这将导致 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>
    

    【讨论】:

    • 感谢您的精彩回答!非常有用!我做了一些更改,但我仍然有我的问题:s 所以我正在编辑我的问题以更具体
    • 我刚刚重写了整个帖子以澄清事情。再次感谢!!!
    猜你喜欢
    • 2017-03-17
    • 2014-09-13
    • 1970-01-01
    • 2014-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多