我是 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 中找到更多详细信息.


评论关闭
IT干货网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!