Spring在Servlet中的@Autowired注解

5

我在我的应用程序中使用Spring框架(2.5.4),并且使用了加载时织入,所有地方都可以正常工作(在Spring bean中,在非Spring实体中),只有当我尝试在一个带有@Configurable注释的servlet中自动装配字段时,我会得到一个漂亮的NullPointerException...


@Configurable(dependencyCheck=true)
public class CaptchaServlet extends HttpServlet{
    @Autowired
    private CaptchaServiceIface captchaService;

    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
    //    ApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(config.getServletContext());
    //    captchaService = (CaptchaServiceIface) ctx.getBean("captchaService");
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Captcha c = captchaService.getCatpcha();
        req.getSession().setAttribute("captchaAnswer", c.getAnswer());
        resp.setContentType("image/png");
        ImageIO.write(c.getImage(), "png", resp.getOutputStream());
    }
}

<context:load-time-weaver/>
<context:spring-configured/>
<context:component-scan base-package="cz.flexibla2" />

有没有关于我做错了什么的建议?谢谢。

1
我不确定,但可能是因为Servlet类由Servlet容器加载而不是Spring容器。 - Abhinav Sarkar
2
@abhin4v: 装载时织入的想法是允许任何东西装载类,而不仅限于Spring。 - skaffman
@malejpavouk,这种行为的最终解决方案是什么?你能分享一下吗? - Mahmoud Saleh
手动使用WebContextUtils进行查找。我在某个地方看到过,也可以通过使用Aspectj代理来修复这个问题(但我没有尝试过)。我还将此作为错误报告到Spring JIRA中,但被标记为不修复(因为设计有缺陷)。 - malejpavouk
2个回答

6
这可能是因为Servlet容器在Spring上下文被初始化之前实例化和初始化Servlet,而正是Spring上下文处理了负载时间织入。你的是否在Servlet Spring上下文内部处理,还是在Web应用程序级别处理?前者几乎肯定行不通(出于上述原因),但Web应用程序级别的配置可能会起作用(使用ContextLoaderListener)。

我正在web.xml中使用contextLoaderLister...看起来一些成功注入的bean是在servlet之前创建的... - malejpavouk
上下文:load-time-weaver标签本身位于Spring配置文件中...不知道是否重要,但我正在使用spring-agent来检测我的代码。 - malejpavouk

3

另请参阅邮件列表讨论和https://bugs.eclipse.org/bugs/show_bug.cgi?id=317874的错误报告。我同意,直观地在servlet上使用@Configurable注释应足以向Spring框架指示在实例化时将由Spring配置servlet,当使用<context:spring-configured/>时。我还观察到,当使用-javaagent:/path/to/aspectjweaver.jar而不是spring-instrument * .jar或spring-agent.jar时,可以实现所需的行为。请在https://jira.springframework.org/browse/SPR上提出Spring Jira问题。我认为问题可能是servlet类 - 而不是servlet的实例,而是加载在调用spring ContextLoaderListener之前,因此Spring框架没有机会在加载servlet类之前对其进行处理。

加载时编织的Spring仪器似乎是基于能够在类字节码加载之前转换它。如果Servlet容器持有在被Spring转换之前获取的Class对象实例,则它(Servlet容器)将无法生成转换后的类实例,Spring也无法使用该Class对象上的工厂方法来处理创建的实例。


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