当前位置: 首页 > 知识库问答 >
问题:

将原型bean注入单例bean

阎星河
2023-03-14

我刚接触Spring,正在尝试理解“将一个原型bean注入一个单例bean”的概念。根据我在singleton中的理解,每个Spring IoC容器只有一个实例,不管您检索它多少次。validator.validate(requestId);,因为仍未实例化private RequestValidator validator。我开发了以下示例,其中在单个bean中给出了原型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" />

RequestProcessor.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;
    }
}
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

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

另一种方式:

<!-- 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" />

如果我调用我的main方法,我会看到下面的output+error:这里codevalidator.validate(requestId);执行,private RequestValidator validator;没有安装,为什么会出现空指针异常。

我在下面的代码中显示了:

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)

共有1个答案

吴欣然
2023-03-14

注入只发生一次,当Spring上下文启动时。如果bean具有prototype作用域,那么Spring将为每次注入创建新的原型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" />

在这种情况下,RequestProcessorbean都将有自己的RequestValidatorbean实例。

查找方法是一种方法,您应该在每次需要新的原型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();
}
<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" />
 类似资料:
  • 我目前有一个简单的bean作为pojo,我正在将其注入到工作线程中,工作线程是用定义的。 我发现bean被正确地注入到原型中,被重新初始化,并且所有的值都返回。 下面是注入的代码: POJO: } 我知道bean正在重新创建,因为调试器中的ID发生了变化,并且被打印到控制台。 用这种方式将单例注入到原型中有什么问题吗? 多谢了。

  • 我有一个用于原型bean的FactoryBean,如下所示: 我希望在控制器中自动连接它,并且每当我尝试访问属性时(通过,从获得一个新的原型实例: 但是,这从来不会调用getObject()。如果我注入ApplicationContext一个直接访问bean,它就会工作,提供一个全新的属性bean: 如何直接使用@autowired注入来实现?

  • Spring具有bean类型/作用域,如 -singleton bean(每个应用程序上下文只有一个bean), -prototype bean(每个请求一个新bean) 现在,如果在单例bean中有对原型bean的引用,是否有办法在对单例bean的每个请求中获得一个新的原型bean(在单例bean中)。< br >如果是,配置会是什么样的?

  • Spring在这里需要一些帮助。在我们的项目中,我们使用XML和注释配置(Spring 4.1) 最近我遇到了以下任务: 我有一个范围原型的bean列表,它们都实现了相同的接口。 此外,我有一个单独的bean,它有< code>execute方法。在方法内部,bean应该访问这些原型bean的列表。 每次执行“execute”方法时,我都想访问这些原型bean的不同实例)。在singleton中,

  • 我使用和注释来注入一个原型bean。 然而,注入bean的行为类似于单例bean。有没有办法在mockito中注入一个原型范围bean? 我正在使用运行JUnit,并使用运行初始化模拟。

  • 我正在使用Spring3中的查找方法注入将原型bean注入到单例bean中,如这里的Spring文档中所述。在我的原型bean中,我对ApplicationContext.xml中声明的另一个bean有依赖关系。查找方法注入似乎工作正常,因为我的原型bean被注入到我的单例bean中,然而,原型的依赖项根本没有被注入。当通过查找方法返回原型时,依赖关系是否可以以正常的方式注入到原型bean中?如果