Spring中的Spring Prototype scoped bean

Ang*_*gad 29 java spring

我试图在单例bean中注入一个原型bean,这样每个对单例bean方法的新调用都有一个原型bean的新实例.

考虑一个单例bean,如下所示:

    @Component
    public class SingletonBean {
       @Autowired 
       private PrototypeBean prototypeBean;

       public void doSomething() {
         prototypeBean.setX(1);
         prototypeBean.display();
       }
    }
Run Code Online (Sandbox Code Playgroud)

我希望每次调用doSomething()方法时,都会使用一个新的PrototypeBean实例.

下面是原型bean:

     @Component 
     @Scope(value="prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
     public class PrototypeBean {
        Integer x;

        void setX(Integer x) {
         this.x = x;
        }

        void display() {
          System.out.println(x);
        }
    }
Run Code Online (Sandbox Code Playgroud)

似乎正在发生的事情是,春天在doSomething()方法中交出一个新的PrototypeBean实例时非常渴望.也就是说,doSomething()方法中的2行代码在每行中创建了一个新的prototypeBean实例.所以在第二行 - prototypeBean.display()打印出NULL.

这是预期的行为还是我错过了正确注入原型bean的一些配置?

Fra*_*eth 39

从Spring 文档:

您不需要<aop:scoped-proxy/>与作为单例或原型作用域的bean一起使用.如果您尝试为单例bean创建范围代理,则会引发BeanCreationException.

对于版本3.2 文档,文档似乎有所改变,您可以在其中找到以下句子:

您不需要<aop:scoped-proxy/>与作为单例或原型作用域的bean一起使用.

似乎不期望你使用代理原型bean,因为每次请求BeanFactory它时都会创建一个新的实例.


为了让你的原型bean有一种工厂,你可以使用ObjectFactory如下:

@Component
public class SingletonBean {

    @Autowired
    private ObjectFactory<PrototypeBean> prototypeFactory;

    public void doSomething() {
        PrototypeBean prototypeBean = prototypeFactory.getObject();
        prototypeBean.setX(1);
        prototypeBean.display();
    }
}
Run Code Online (Sandbox Code Playgroud)

并且您的原型bean将声明如下:

@Component 
@Scope(value="prototype")
public class PrototypeBean {
    // ...
}
Run Code Online (Sandbox Code Playgroud)

  • 如果我不使用proxyMode,那么在单例中自动装配原型并不会每次都给出新bean.相反,要实现这一点,我必须做的是从spring的applicationContext调用getBean().但是,我希望简单地将原型bean自动装配.我不确定这是否可行. (3认同)

小智 17

Singleton bean只创建一次,因此注入的原型bean也将在singleton bean的实例化时创建一次.原型bean的相同实例将用于每个请求.

如果将在运行时为每个请求创建原型bean的新实例,则可以使用下面的方法Injection

public class Singleton {
    private Prototype prototype;

    public Singleton(Prototype prototype) {
        this.prototype = prototype;
    }

    public void doSomething() {
         prototype.foo();
    }

    public void doSomethingElse() {
        prototype.bar();
    }
}

public abstract class Singleton {
    protected abstract Prototype createPrototype();

    public void doSomething() {
        createPrototype().foo();
    }

    public void doSomethingElse() {
        createPrototype().bar();
    }
}


<bean id="prototype" class="ch.frankel.blog.Prototype" scope="prototype" />
<bean id="singleton" class="sample.MySingleton">
   <lookup-method name="createPrototype" bean="prototype" />
</bean>
Run Code Online (Sandbox Code Playgroud)

  • 你的答案很好,我实际上已经使用过了,但这个例子并不清楚.为什么你有两个名为Singelton的课程?第一个实现第二个吗?什么是MySingleton? (4认同)