gpt4 book ai didi

spring - 将原型(prototype) bean 注入(inject)单例 bean

转载 作者:行者123 更新时间:2023-12-04 12:05:08 27 4
gpt4 key购买 nike

我是 Spring 新手并试图理解“ 将原型(prototype) bean 注入(inject)单例 bean ”的概念。据我了解在单例中,每个 Spring IoC 容器只有一个实例,无论您检索多少次 . validator.validate(requestId); , 因为还是 private RequestValidator validator未实例化。
我开发了下面的示例,其中在单例 bean 中我给出了原型(prototype) bean 的引用,如下所示:

<bean id="requestProcessor" class="com.injection.testing.RequestProcessor">
<property name="validator" ref="validator" />
</bean>

<bean id="validator" class="com.injection.testing.RequestValidator" scope="prototype" />

请求处理器.java
public class RequestProcessor {
private RequestValidator validator;

public RequestProcessor(){
System.out.println("Constructor:: RequestProcessor instance created!");
}

public void handleRequest(String requestId){
System.out.println("Request ID : "+ requestId);
validator.validate(requestId);
}

public RequestValidator getValidator() {
return validator;
}

public void setValidator(RequestValidator validator) {
this.validator= validator;
}
}

RequestValidator.java
public class RequestValidator {
private List<String> errorMessages = new ArrayList<String>();

public RequestValidator() {
System.out.println("Constructor:: RequestValidator instance created!");
}

// Validates the request and populates error messages
public void validate(String requestId){
System.out.println("RequestValidator :"+requestId);
}

public List<String> getErrorMessages() {
return errorMessages;
}
}

现在,当我调用 main 方法时,我看到以下输出:
MainDemo.java
public class MainDemo {

public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");

RequestProcessor processor = (RequestProcessor) context.getBean("requestProcessor");
processor.handleRequest("1212");
System.out.println("------------------------");
processor.handleRequest("1213");
}
}

输出是:
Constructor:: RequestProcessor instance created!
Constructor:: RequestValidator instance created!
Request ID : 1212
RequestValidator :1212
------------------------
Request ID : 1213
RequestValidator :1213

现在查看输出,看起来像是第二次调用 processor.handleRequest("1213"); bean 没有被实例化,而是已经实例化的 bean 被使用,这就是为什么构造函数不会被再次调用。所以原型(prototype) bean validator仅充当单例 bean。

对我来说:预计当我从应用程序上下文中获取 requestProcessor 时,它将与 new validator 连接。正如我们声明的验证器 bean 是原型(prototype)范围的。但这不会发生。

如何解决?我的理解正确吗?

其他方式:
<!-- Lookup way  -->
<bean id="requestProcessor" class="com.injection.testing.RequestProcessor" >
<lookup-method name="getValidator" bean="validator" />
</bean>

<bean id="validator" class="com.injection.testing.RequestValidator" scope="prototype" />

如果我调用我的主要方法,我会在下面看到 输出+错误 : 这里代码 validator.validate(requestId);执行, private RequestValidator validator;不是 instatiated 以及为什么会出现空指针异常。

我在下面的代码中显示:
public class MainDemo {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");

RequestValidator requestValidator = (RequestValidator) context.getBean("validator");

RequestProcessor processor = (RequestProcessor) context.getBean("requestProcessor");
processor.handleRequest("1212");
System.out.println("------------------------");
processor.handleRequest("1213");
}
}

现在我看到以下错误:
Constructor:: RequestProcessor instance created!
Constructor:: RequestValidator instance created!
Request ID : 1212
Exception in thread "main" java.lang.NullPointerException
at com.injection.testing.RequestProcessor.handleRequest(RequestProcessor.java:12)
at com.injection.testing.MainDemo.main(MainDemo.java:14)

最佳答案

当 Spring 上下文启动时,注入(inject)只发生一次。如果 bean 有 prototype范围内,Spring 将为每次注入(inject)创建新的原型(prototype) bean。但是每次调用它的方法时都不会创建原型(prototype)bean。让我们考虑下一个例子:

<bean id="firstRequestProcessor" class="com.injection.testing.RequestProcessor">
<property name="validator" ref="validator" />
</bean>

<bean id="secondRequestProcessor" class="com.injection.testing.RequestProcessor">
<property name="validator" ref="validator" />
</bean>


<bean id="validator" class="com.injection.testing.RequestValidator" scope="prototype" />

在这种情况下, RequestProcessor bean 将拥有自己的 RequestValidator 实例 bean 。

Lookup方法是方法,每次需要原型(prototype)bean的新实例时都应该调用。最好做这个方法 abstract , 因为无论如何 Spring 都会自动覆盖这个方法。例如:
public class abstract RequestProcessor {

public void handleRequest(String requestId){
System.out.println("Request ID : "+ requestId);
RequestValidator validator = createValidator(); //here Spring will create new instance of prototype bean
validator.validate(requestId);
}

protected abstract RequestValidator createValidator();
}

请注意, createValidator返回 RequestValidator 的实例并且没有任何参数。你也不需要私有(private)类变量 validator .在这种情况下,bean 的配置将如下所示:
<bean id="requestProcessor" class="com.injection.testing.RequestProcessor" >
<lookup-method name="createValidator" bean="validator" />
</bean>

<bean id="validator" class="com.injection.testing.RequestValidator" scope="prototype" />

现在每次调用 createValidator方法,Spring 将创建 validator 的新实例 bean 。

您可以在 documentation 中找到更多详细信息.

关于spring - 将原型(prototype) bean 注入(inject)单例 bean,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41457738/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com