java - 如何在方法调用中实例化一个新 bean?

标签 java spring instantiation

我有这样的东西:

@Controller
@Scope("session")
public class MyServletController {



    @Autowired
    private QueryRunner queryRunner;

    HashMap<String, Result> resultsMap; 

    @RequestMapping("/submitQuery")
    public ModelAndView submitQuery(HttpServletRequest request)
    {
    String sessionId = request.getParameter("sessionId");
    Result r = queryRunner.runQuery(sessionId, request.getParameter("otherdata"));
    resultsMap.put(sessionId, r);
    }



    @RequestMapping("/getResult")
    @ResponseBody
    public void saveTextLinks(HttpServletRequest request,
            HttpServletResponse response) throws IOException
    {
     String sessionId = request.getParameter("sessionId");      
     //return sessionId result from resultsMap
    }

 }


<bean id="queryRunner"
    class="com.myproject.QueryRunner"
    scope="prototype">
    <aop:scoped-proxy />


    <property name="errorMessageA" value="${error.messagea}"></property>
    <property name="errorMessageB" value="${error.messageb}"></property>

</bean>

我想要的是 Servlet Controller 是 session 范围的,但每个请求都需要实例化一个新的 QueryRunner,以便在一次发送多个请求时不会产生任何干扰。

如何配置 Spring 来执行此操作?

诱人的解决方案就是:

    @RequestMapping("/submitQuery")
    public ModelAndView submitQuery(HttpServletRequest request)
    {
    queryRunner = new QueryRunner(); //<-----
    String sessionId = request.getParameter("sessionId");
    Result r = queryRunner.runQuery(sessionId, request.getParameter("otherdata"));
    resultsMap.put(sessionId, r);
    }

最佳答案

[...] but each request needs to instantiate a new QueryRunner as to not have any interference if multiple requests are sent at once

您的设置已经做到了这一点。您的 QueryRunner bean 声明为

<bean id="queryRunner"
    class="com.myproject.QueryRunner"
    scope="prototype">
    <aop:scoped-proxy />

这意味着 Spring 将在请求此类 bean 的任何地方注入(inject)代理

@Autowired
private QueryRunner queryRunner;

并且代理每次都会在内部将所有调用委托(delegate)给新初始化的 bean。请注意,这意味着如果您执行类似的操作

Result r1 = queryRunner.runQuery(sessionId, request.getParameter("otherdata"));
Result r2 = queryRunner.runQuery(sessionId, request.getParameter("evenmoredata"));

每个 runQuery 调用在其底层都是在不同的 QueryRunner 实例上调用的。

如果您希望有一个跨越请求整个生命周期的QueryRunner bean,只需声明该 bean 具有请求范围

<bean id="queryRunner"
    class="com.myproject.QueryRunner"
    scope="request">
    <aop:scoped-proxy />

在幕后(假设使用默认的 MVC 配置),Spring 会将对 HttpServletRequest 的引用存储在可通过 static 访问的 ThreadLocal 上下文中。 > 实用类。它将实际的 bean 存储在 HttpServletRequest 属性中。

当您最终在代理上调用runQuery(存储在“@Autowired”字段中)时,Spring 将首先检查现有 bean 的上下文。如果找到,它将使用它来调用您的方法。如果没有,它将初始化一个新实例,将其存储在上下文中,然后使用它。这样,前面的例子就可以了

Result r1 = queryRunner.runQuery(sessionId, request.getParameter("otherdata"));
Result r2 = queryRunner.runQuery(sessionId, request.getParameter("evenmoredata"));

实际上是在同一个 QueryRunner 实例上调用 runQuery

由于 HttpServletRequest 属性在每次请求后都会被清除,因此您的请求范围的 bean 实例也会被清除。

关于java - 如何在方法调用中实例化一个新 bean?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31418507/

相关文章:

java - 显示按下的 Jbutton 的行和列

java - 将 Java 转换为 Objective-c(Android 到 iOS)

c++ - 使用 protected 构造函数在 C++ 中实例化对象

java - 创建泛型类的公共(public)内部类的实例

java - 通过继承隐藏字段

java - 打印数组 : memory address or its content?

java - 重用复杂的 spring-fox swagger 注释

java - 使用 @PropertySource 和外部 JSON 文件进行 Spring 属性配置

java - 摆脱 Tomcat 中的 Spring 日志

c# - 类的实例不存在?