通过从内存中清除Spring Prototype-beans来澄清情况

Kir*_* Ch 6 java spring prototype spring-mvc javabeans

我想了解我是否应该自己手动清理内存中的原型bean.

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

因此,您似乎应该自己清理原型bean.

然而.

我正在使用VisualVM 内存分析器.我创建了许多原型bean.你可以看到它们的51个实例.

在此输入图像描述

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

在此输入图像描述

所以有人可以澄清这种情况吗?原型bean是否被垃圾收集器成功清除,或者我们应该手动清除它们(如果是,如何)?


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

在我们的真实项目中,我们有超过400个组件注释为Prototype-beans,我可以看到相同的行为.我已经向我们的系统提出了许多请求,通过VisualVM查看了一些创建的原型bean,然后在垃圾收集器清理内存后,所有原型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();
}
Run Code Online (Sandbox Code Playgroud)

原型bean的测试示例:

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

    private int number;

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

    public void test1(){

    }

}
Run Code Online (Sandbox Code Playgroud)

Ant*_*ink 1

创建原型 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
    }

}  
Run Code Online (Sandbox Code Playgroud)