Spring没有注入beans,我做错了什么?

3

我正在尝试简单地尝试Spring,但似乎缺少某些东西。它似乎可以很好地加载Spring和bean,但是当涉及使用autowired注入这些bean时,它无法正常工作。有人有线索吗?

用于Spring和mainServlet的web.xml部分:

    <welcome-file-list>
        <welcome-file>/login.jsp</welcome-file>
    </welcome-file-list>

    <!-- Spring Dependency Injection -->

     <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>

  <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
    </listener-class>

<!-- Login Filter -->
<filter>
    <filter-name>LoginFilter</filter-name>
    <filter-class>com.nortal.pirs.presentation.web.LoginFilter</filter-class>
    <init-param>
        <param-name>secretParameter</param-name>
        <param-value>8392</param-value>
    </init-param>
</filter>

<filter-mapping>
        <filter-name>LoginFilter</filter-name>
        <url-pattern>/MainServlet</url-pattern>
        <servlet-name>MainServlet</servlet-name>
</filter-mapping>

<!-- Main Servlet -->
<servlet>
<servlet-name>MainServlet</servlet-name>
<servlet-class>com.nortal.pirs.presentation.web.MainServlet</servlet-class>

<servlet-mapping>
    <servlet-name>MainServlet</servlet-name>
    <url-pattern>/main/*</url-pattern>
</servlet-mapping>

Spring应用程序上下文文件(尽管我认为我还加载了太多不必要的东西,但是这是出于绝望,因为它没有工作):

    <?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:aop="http://www.springframework.org/schema/aop"
    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/aop 
        http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
        http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context-3.1.xsd">

    <context:annotation-config />

    <!-- Turn on AspectJ @Configurable support -->
    <context:spring-configured />

    <context:component-scan base-package="com.nortal.pirs.test.independent" />
    <context:component-scan base-package="com.nortal.pirs.businesslogic.logic" />
    <context:component-scan base-package="com.nortal.pirs.presentation.vaadin" />
    <context:component-scan base-package="com.nortal.pirs.presentation.vaadin.views" />
    <context:component-scan base-package="com.nortal.pirs.presentation.web" />

    <!-- Turn on @Autowired, @PostConstruct etc support -->
    <bean
        class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
    <bean
        class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" />

</beans>

UserManagerLogic(后续需要使用@autowired注入到MainServlet中的bean):

@Component("UserManager")
public class UserManagerLogic implements UserManagerInterface {

MainServlet:

 @Service
public class MainServlet extends HttpServlet {

    @Autowired
    @Qualifier("UserManager")
    private UserManagerInterface userManager;
    Logger log;

    public MainServlet() {
        log = Logger.getLogger(getClass());
    }

    public boolean userLoggedIn(String username, String password) {     
        return SecurityManager.getInstance().credentialsValid(username, password);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        processRequest(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        processRequest(req, resp);
    }

    public void processRequest(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {

        HttpSession session = ((HttpServletRequest) request).getSession();

        String username = (String) session.getAttribute("username");
        boolean authenticated = (boolean) session.getAttribute("authenticated");

        User user = userManager.getUserByEmail(username);

        WelcomeGenerator welcomeGenerator = new WelcomeGenerator();

        if (authenticated) {
            generateResponse(response, welcomeGenerator.WelcomeMessage(user), "The secret code is " + session.getAttribute("secretParameter"));
        } else {
            generateResponse(response, welcomeGenerator.wrongCredentialsMessage(username), "Secret code is hidden, because authentication failed");
        }
    }

    public void generateResponse(HttpServletResponse response, String welcomeMessage, String additionalData) throws IOException {       
        HtmlGenerator generator = new HtmlGenerator("PIRS");
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();

        out.write(generator.printHeader());
        out.write(generator.printCenter(welcomeMessage));
        out.write(generator.printCenter(additionalData));
        out.write(generator.printFooter());
    }

    public UserManagerInterface getUserManager() {
        return userManager;
    }

    public void setUserManager(UserManagerInterface userManager) {
        this.userManager = userManager;
    }               
}

结果当然是在调用userManager时出现了空指针异常,这个userManager本来应该被Spring注入的。

java.lang.NullPointerException
    at com.nortal.pirs.presentation.web.MainServlet.processRequest(MainServlet.java:58)
    at com.nortal.pirs.presentation.web.MainServlet.doPost(MainServlet.java:47)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:641)

然而,Spring确实加载bean,只是不注入它们,并且不会抛出任何错误,为什么会这样?
2013-03-08 03:48:42,834 [localhost-startStop-1] INFO  org.springframework.beans.factory.support.DefaultListableBeanFactory - Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@6a4ac9fb: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,org.springframework.context.config.internalBeanConfigurerAspect,mainController,SecurityManager,**UserManager**,VisitManager,**mainServlet**,org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#0,org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#0,org.springframework.context.annotation.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor#0]; root of factory hierarchy

为什么不使用控制器而不是Servlet? - Arun P Johny
@service 注解不适用于 Servlet。请查看此链接,可能与您遇到的问题相同:http://stackoverflow.com/questions/14283750/instantiationexception-using-spring-injection - SRy
2个回答

1
你的servlet没有被标记为@Configurable。由于它的生命周期不受Spring控制,这是唯一让它自动装配的方法。
哦,还有,你的servlet绝对不是一个@Service

这不仅仅是如此。您的servlet未由Spring管理,因此无法将其他bean注入其中。 - Sotirios Delimanolis
@Sotirios:那不是真的。请参阅"使用AspectJ和Spring进行依赖注入领域对象"。它针对领域对象,但适用于任何内容。 - Ryan Stewart
在这个问题的背景下,Servlet容器将实例化他的MainServlet,那么Spring如何知道自动装配任何内容到其中呢? - Sotirios Delimanolis
@Sotirios:使用AspectJ的编译时或加载时字节码织入,您可以让Spring控制任何对象的构建,而不仅仅是它管理的bean。我先前评论中的链接是参考指南中描述其工作原理的部分。 - Ryan Stewart
我也尝试过使用Configurable,但没有任何改变,除了将Service更改为Configurable之外,还需要做什么?另外,我如何使所有这些servlet成为Spring可管理的? - Arturas M
如果你刚开始学习Spring,你可能不想使用@Configurable,因为它是一个相当高级的概念。没有这个东西,正如已经提到的那样,你只能管理那些由Spring自己创建的对象--也就是你使用XML或注释设置的bean。 - Ryan Stewart

0

这是因为Servlets由Spring容器管理。 Servlets由Servlet容器管理。

但幸运的是,Spring提供了一个实用方法来获取SpringApplicationContext以从Servlet中获取bean。 这可以使用WebApplicationContextUtils来完成。

示例代码

ApplicationContext ctx = 
                    WebApplicationContextUtils.
                          getWebApplicationContext(session.getServletContext());
UserManagerInterface userManager = (UserManagerInterface )ctx.getBean("UserManager");

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接