简体   繁体   English

用原型范围标记的 Bean 在 Spring 中不起作用

[英]Bean marked with prototype scope not working in Spring

I have two beans, Parent and Child.我有两个 bean,Parent 和 Child。 Child bean I have declared as of Protoype scope.我已声明为 Protoype 范围的子 bean。
I want new child object is used to call any child's method in the Parent class.我希望新的子对象用于调用父类中的任何子对象的方法。 For eg.例如。 in the below example,I want statement 1 calls method sayHi on different child object and statement 2 calls sayHi1 on different child object.在下面的示例中,我希望语句 1 在不同的子对象上调用方法sayHi ,语句 2 在不同的子对象上调用sayHi1

One way is to implement ApplicationContextAware and get new child object using context.getBean("") before calling any child's method.一种方法是在调用任何子对象的方法之前实现ApplicationContextAware并使用context.getBean("")获取新的子对象。 But i don't want to do that.但我不想那样做。

Is there any other alternative?还有其他选择吗?

@Component
public class Parent{

    @Autowired
    Child child;

    public void sayHello(){     
        child.sayHi();           -------------- (1)
    }

    public void sayHello1(){    
        child.sayHi1();          --------------- (2)
    }
}

@Component
@Scope(value=BeanDefinition.SCOPE_PROTOTYPE)
public class Child{

    public void sayHi(){
        System.out.println("Hi Spring 3.0");

    }

    public void sayHi1(){
        System.out.println("Hi1 Spring 3.0 ");      
    }

}

The fix is simply to mark the prototype bean as a scoped proxy, what this means is that a when you inject a bean of a smaller scope into a larger scope(like in your case where a prototype is injected into a singleton) then a proxy of the bean will be injected into the larger scope and when methods of the bean are invoked via proxy, the proxy understands the scope and will respond appropriately.修复只是将原型 bean 标记为作用域代理,这意味着当您将较小作用域的 bean 注入较大作用域时(例如将原型注入到单例中的情况)然后是代理bean 将被注入更大的作用域,当 bean 的方法通过代理调用时,代理理解作用域并做出适当的响应。

@Component
@Scope(value=BeanDefinition.SCOPE_PROTOTYPE, proxyMode=ScopedProxyMode.TARGET_CLASS)
public class Child{

Here is a reference这是一个参考

Another option could be to use something called lookup method injection described here另一种选择是使用这里描述的称为查找方法注入的东西

I think you have to make a new Child yourself each time or indeed use the spring context to get a fresh bean.我认为你每次都必须自己创建一个new Child或者确实使用 spring 上下文来获取一个新鲜的 bean。

Spring will only create a new instance when it needs to inject something (in case of prototype). Spring 只会在需要注入某些内容时(在原型的情况下)才会创建一个新实例。 When you are in a class you are effectively out of the scope of spring.当你在课堂上时,你实际上已经超出了 spring 的范围。

Here is a similar post: @Scope("prototype") bean scope not creating new bean这是一个类似的帖子: @Scope("prototype") bean scope not created new bean

http://static.springsource.org/spring/docs/3.0.0.M3/reference/html/ch04s04.html#beans-factory-scopes-prototype Parts 4.4.2 and 4.4.3 are relevant. http://static.springsource.org/spring/docs/3.0.0.M3/reference/html/ch04s04.html#beans-factory-scopes-prototype Parts 4.4.2 和 4.4.3 是相关的。

Prototype scope means Spring will give you a new Child object each time you ask for one (via injection or an explicit bean retrieval from an app context).原型范围意味着每次您请求一个新的Child对象时,Spring 都会为您提供一个新的Child对象(通过注入或从应用程序上下文中显式的 bean 检索)。 In your Parent class, you only asked for a Child once, so you only got one.在你的Parent类中,你只要求一个Child一次,所以你只有一个。 If you want two different Child objects in your Parent , then autowire two:如果你想在你的Parent两个不同的Child对象,那么自动装配两个:

@Component
public class Parent{

    @Autowired
    Child child;

    @Autowired
    Child child1;

    public void sayHello(){     
        child.sayHi();
    }

    public void sayHello1(){    
        child1.sayHi1();
    }
}

You can't do it.你不能这样做。 After the ApplicationContext is up, only one bean will be injected into child. ApplicationContext 启动后,只有一个 bean 会被注入到 child 中。 For each parent a new child will be created.将为每个父级创建一个新子级。

The thing is a parent have only one child, so your 2 methods will invoke only that child methods.事情是父母只有一个孩子,所以你的 2 个方法只会调用那个孩子的方法。

What exactly you are trying to achieve?你到底想达到什么目标? I am sure there is a proper solution for it.我相信有一个适当的解决方案。

Answers are already given by others, I will include a theory which can be helpful其他人已经给出了答案,我将包含一个可能有用的理论

To turn component to prototype we do this - You probably already know this :)要将组件转换为原型,我们这样做 -您可能已经知道这一点:)

@Scope(value=BeanDefinition.SCOPE_PROTOTYPE)
Class B{ .....}

This will only help if the class B is called as .getBean(B.class) OR the class Autowiring it is also a Prototype.这仅在类 B 被称为.getBean(B.class).getBean(B.class)它也是原型时才有帮助。


Now ,suppose we do like this现在,假设我们这样做

 @Component
    Class A{
   
          @Autowired
          Class B;
     }
   

Class A is singleton and it assumes every instance of class B as Singleton too : | A 类是单例,它也假定 B 类的每个实例都是单例:|


Now, how to tell class A that class B is Prototype?现在,如何告诉 A 类 B 类是 Prototype?

Simple , just include proxyMode=ScopedProxyMode.TARGET_CLASS and class A will know that class B is Prototype !很简单,只需要包含proxyMode=ScopedProxyMode.TARGET_CLASS并且 class A 就会知道 class B 是 Prototype !

It will look something like below :它看起来像下面这样:

@Component
@Scope(value=BeanDefinition.SCOPE_PROTOTYPE, proxyMode=ScopedProxyMode.TARGET_CLASS)
public class B{.....}

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM