简体   繁体   English

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

[英]How do I instantiate a new bean in a method call?

I have something like this: 我有这样的事情:

@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>

What I want is that the Servlet Controller is session scoped, but each request needs to instantiate a new QueryRunner as to not have any interference if multiple requests are sent at once. 我想要的是Servlet控制器在会话范围内,但是每个请求都需要实例化一个新的QueryRunner ,以免一次发送多个请求时不会受到任何干扰。

How do I configure Spring to do this? 如何配置Spring来做到这一点?

The tempting solution is to just go: 诱人的解决方案是:

    @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,以确保一次发送多个请求时不会受到任何干扰

Your setup already does that. 您的设置已经做到了。 Your QueryRunner bean is declared as 您的QueryRunner bean被声明为

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

This means that Spring will inject a proxy wherever such a bean is requested, for example 这意味着Spring将在任何需要这种bean的地方注入代理,例如

@Autowired
private QueryRunner queryRunner;

and the proxy will, internally, delegate all calls to newly initialized beans every time. 并且代理将在内部每次将所有调用委派给新初始化的bean。 Note that this means that if you do something like 请注意,这意味着如果您执行类似

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

each of those runQuery calls are, underneath it all, invoked on different QueryRunner instances. 所有这些runQuery调用都在不同的QueryRunner实例下被调用。

If you want to have a single QueryRunner bean that spans the entire lifecycle of a request, just declare the bean to have the request scope 如果您想拥有一个跨请求整个生命周期的QueryRunner bean,只需声明该bean具有请求范围

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

Behind the scenes (assuming the default MVC configuration), Spring will store a reference to the HttpServletRequest in a ThreadLocal context accessible through a static utility class. 在幕后(假设使用默认的MVC配置),Spring将在对ThreadLocal上下文的访问中存储对HttpServletRequest的引用,该上下文可通过static实用程序类访问。 It will store the actual bean in the HttpServletRequest attributes. 它将实际的bean存储在HttpServletRequest属性中。

When you eventually invoke runQuery on the proxy (which is stored in the `@Autowired field), Spring will first check the context for a existing bean. 当您最终在代理上调用runQuery时(存储在`@Autowired字段中),Spring将首先检查上下文中是否存在现有的bean。 If it finds one, it will use it to invoke your method. 如果找到一个,它将使用它来调用您的方法。 If it doesn't, it will initialize a new instance, store it in the context, then use it. 如果没有,它将初始化一个新实例,将其存储在上下文中,然后使用它。 This way, the previous example 这样,前面的例子

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

is actually invoking runQuery on the same QueryRunner instance. 实际上是在同一QueryRunner实例上调用runQuery

Since HttpServletRequest attributes are cleared after each request, so will your request-scoped bean instances. 由于在每个请求之后都会清除HttpServletRequest属性,因此您的请求范围的Bean实例也会被清除。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 我如何通过将对象作为参数传递来实例化CDI bean,就像我从参数化构造函数中以普通Java实例化新对象一样? - How do I instantiate a CDI bean by passing an object as parameter just like I instantiate a new object in plain Java from a parameterized constructor? 如何实例化在Spring配置中声明为Bean的属性? - How do I instantiate an attribute that is declared as a bean in the spring config? 如何实例化绘画方法? - How do I instantiate a paint method? 用Java反射如何实例化一个新对象,然后调用一个方法就可以了? - With Java reflection how to instantiate a new object, then call a method on it? 如何从Singleton bean中调用另一个Singleton bean? - How do I call another Singleton bean from a Singleton bean? 如何在每次迭代时实例化一个新矩阵? - How do I instantiate a new matrix every iteration? 如何在这样的Java静态方法中实例化BigInteger? - How do I instantiate a BigInteger in a java static method like this? 如何在Java中实例化泛型方法参数的实例? - How do I instantiate an instance of a generic method parameter in Java? 为什么我需要实例化我的类才能在静态方法中调用我的方法? - Why do I need to make instantiate my class to call my method in the static method? Spring @Autowired - 实例化新bean - Spring @Autowired - Instantiate new bean
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM