从内存中清理 Spring Prototype-beans 澄清情况

Clarify a situation with a cleaning Spring Prototype-beans from memory

我想了解我是否应该自己手动从内存中清除原型 bean。

在Spring文档中你可以看到: “客户端代码必须清理原型范围的对象并释放原型 bean 持有的昂贵资源。”

所以看来你应该自己清理prototype-beans。

不过。

我正在使用 VisualVM 内存分析器。 我已经创建了许多原型 bean。您可以看到 51 个实例。

然后你可以看到当垃圾收集器清理内存时的情况——所有的prototype-beans都被清除了.

所以谁能澄清一下情况? prototype-bean 是否被垃圾收集器成功清除,或者我们应该手动清除它们(如果是,如何清除)?


加法。 有些人要求展示创建原型 bean 的代码。实际上,我认为这没有任何意义,因为在特定示例中,我只是将它们创建为测试,而这与从内存中清除原型 bean 的实际情况无关。开发人员可以通过不同的方式创建原型 bean,但它们的未来行为不依赖于或不应依赖于创建方法。

在我们的真实项目中,我们有超过 400 个组件被注释为 Prototype-beans,我可以看到相同的行为。我已经向我们的系统发出了一些请求,通过 VisualVM 看到了一些创建的原型 beans,然后在垃圾收集器清理内存之后所有的原型 bean 都被清除了。

我展示测试代码只是希望那些询问此问题的人能提供一些关于真实行为的有意义的信息而不仅仅是关于这个特定测试 bean 创建的空话

测试原型 bean 的创建 示例:

for(int i=0;i<10;i++){
        Prototype1 prototype1=applicationContext.getBean(Prototype1.class);
        Prototype2 prototype2=applicationContext.getBean(Prototype2.class);

        prototype1.test1();
        prototype2.test2();
}

原型bean的测试示例:

@Service
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class Prototype1 {

    private int number;

    public Prototype1() {
        System.out.println("Prototype1 was created.");
    }

    public void test1(){

    }

}

创建原型 bean 后;您对其生命周期负责。

一旦您没有对该 bean 的引用,它就消失了。原型 bean 和作用域 bean 之间唯一真正的区别是容器如何管理它。

在单元测试中,您不会依赖容器为您提供这些 bean,您只需自己新建它们。

所以要真正回答您的问题,如果您允许应用程序取消引用原型对象,jvm 的默认行为将消除这些 bean。

 public class Example {

    @Scope("prototype")
    public static class SomePrototypeBean{

    }

    @Singleton
    public static class MySingleton{

        @Bean
        private SomePrototypeBean somePrototypeBean;

    }

    public static void main(String[] args){
       // context creation code goes here

       // singleton is created, a prototype injected
       context.getBean(MySingleton.class);
       // NOTE: the prototype injected will last for as long as MySingleton has reference
       // my singleton will exist for as long as the context has reference

       doStuff(context);
       //prototype bean created in the method above will be GCed
    }

    public static void doStuff(Context context){
        context.getBean(MyPrototypeBean.class);
        //since we literally are doing nothing with this bean, it will be 
        // marked for garbage collection
    }

}