【问题标题】:Spring dependency config problemsSpring依赖配置问题
【发布时间】:2014-12-19 10:52:51
【问题描述】:

大家好,

我是 Spring 新手,目前我正在开发一个使用 Spring MVC 和 Spring 依赖注入的 Web 项目。我有三个班。用户服务、家庭控制器和用户。在 HomeController 中,我调用 UserService 的 fetchUser 方法,该方法返回一个新的 User 类实例。这是我用来重现我的真实项目问题的简单逻辑。我没有在这个简单的项目中使用任何数据库。当我调用 fetchUserMethod 时,我得到一个 NullPointerException。我正在使用 Glassfish 4.0。请你帮助我好吗 ? 谢谢!

这是我的 web.xml

        `<?xml version="1.0" encoding="UTF-8"?>
        <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

            <!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
            <context-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>/WEB-INF/spring/aplicationContext.xml</param-value>
            </context-param>

            <!-- Creates the Spring Container shared by all Servlets and Filters -->
            <listener>
                <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
            </listener>

            <!-- Processes application requests -->
            <servlet>
                <servlet-name>appServlet</servlet-name>
                <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
                <init-param>
                    <param-name>contextConfigLocation</param-name>
                    <param-value>/WEB-INF/spring/servlet-context.xml</param-value>
                </init-param>
                <load-on-startup>1</load-on-startup>
            </servlet>

            <servlet-mapping>
                <servlet-name>appServlet</servlet-name>
                <url-pattern>/</url-pattern>
            </servlet-mapping>

        </web-app>`

这是我的 applicationContext.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"
            xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

            <!-- Root Context: defines shared resources visible to all other web components -->

            <bean id="userService" class="services.UserService"/>

            <bean id="homeController" class="controllers.HomeController">
                <property name="userService" ref="userService"/>
            </bean>

        </beans>

这是我的 servlet-context.xml

    <?xml version="1.0" encoding="UTF-8"?>

    <beans:beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xmlns:beans="http://www.springframework.org/schema/beans"
        xmlns:mvc="http://www.springframework.org/schema/mvc" 
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/mvc 
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        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">


        <!-- Enables the Spring MVC @Controller programming model -->
        <mvc:annotation-driven />

        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/WEB-INF/views/" />
            <property name="suffix" value=".jsp" />
        </bean>

        <context:component-scan base-package="controllers"/>

    </beans:beans>

这是我的 HomeController 类

@Controller
public class HomeController {

    private UserService userService;

    @RequestMapping(value = "/home")
    public ModelAndView homePage(HttpServletRequest request, HttpServletResponse response, HttpSession session){



        User user = userService.fetchUser();

        return new ModelAndView("home", "displayName", user.getUserName());
    }

    public UserService getUserService() {
        return userService;
    }

    public void setUserService(UserService userService) {
        this.userService = userService;
    }

}

这是我的用户类

public class User {

    private String userName;

    private String password;

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

}

这是我的 UserService 类

public class UserService {


    public User fetchUser(){

        User user = new User();
        user.setUserName("test");

        return user;
    }
}

【问题讨论】:

  • 请注意,当您遇到异常时,请发布您的堆栈跟踪...

标签: spring configuration dependency-injection


【解决方案1】:

您错过了HomeController 中的@Autowired 注释:

@Autowired
private UserService userService;

【讨论】:

  • 看起来他似乎是在使用 setter 注入它。会不会有问题
【解决方案2】:
  1. 删除homeController bean 定义。

由于您使用的是&lt;context:component-scan base-package="controllers"/&gt;,因此无需声明homeController bean - 它将自动创建,因为它已使用注释@Controller 进行注释。

  1. UserService 自动连接到HomeController using@Autowired` 注释中。有 3 种方法可以做到:
    • 现场注入:
@Autowired
private UserService userService;
  • setter 注入
@Autowired
public void setUserService(UserService userService) {
    this.userService = userService;
}
  • 构造函数注入:
@Autowired
public HomeController(UserService userService) {
    this.userService = userService;
}

首选方法是始终使用构造函数注入

  1. 删除HomeController 中的UserService getter 和setter。

最后,HomeController 类应该是这样的:

@Controller
public class HomeController {
    private final UserService userService;

    @Autowired
    public HomeController(UserService userService) {
        this.userService = userService;
    }

    @RequestMapping(value = "/home")
    public ModelAndView homePage(HttpServletRequest request, HttpServletResponse response, HttpSession session){
        User user = userService.fetchUser();

        return new ModelAndView("home", "displayName", user.getUserName());
    }
}

【讨论】:

  • 非常感谢。还有一个问题。如果我想让我的 UserService 类依赖于另一个类,比如 UserDao,我应该以同样的方式连接吗?
  • 没错。将 UserDAO 作为私有 final 字段,并在 UserService 构造函数中自动装配。
  • 当我将我的 UserDao 定义作为最终定义时,Eclipse 说我应该删除默认构造函数。当我删除它时,glassfish 无法初始化 UserService,因为没有默认构造函数。
  • 可能是 Glassfish 特有的,或者在您的真实代码中您使用需要默认构造函数的 cglib 代理。在这种情况下,我将遵循方法:首先尝试使用字段注入自动装配所有内容(并删除构造函数),如果一切正常,请尝试使用构造函数注入使其工作。
  • 我用@Service 注释了UserService,现在可以了。非常感谢。
【解决方案3】:

这样,Eclipse 将默认构造函数行标记为错误。如果我删除默认构造函数 glassfish 说它无法初始化 UserService 因为没有默认构造函数。

公共类用户服务{

public UserService(){}

private final UserDao userDao;

@Autowired
public UserService(UserDao userDao){
    this.userDao = userDao;
}


public User fetchUser(){

    User user = userDao.fetchUser();

    return user;
}

}

【讨论】:

    猜你喜欢
    • 2017-10-14
    • 1970-01-01
    • 2018-07-10
    • 2012-10-14
    • 2017-03-20
    • 2015-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多