Spring bean destroy-method,singleton和prototype范围

我是Spring框架的新手,从一些教程开始学习它。

我有以下文件,

#MainProgram.java

package test.spring; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MainProgram { public static void main(String[] args) { AbstractApplicationContext context = new ClassPathXmlApplicationContext("Bean.xml"); HelloSpring obj = (HelloSpring) context.getBean("helloSpring"); obj.setMessage("My message"); obj.getMessage(); context.registerShutdownHook(); } } 

#HelloSpring.java

 package test.spring; public class HelloSpring { private String message; public void setMessage(String message){ this.message = message; System.out.println("Inside setMessage"); } public void getMessage(){ System.out.println("Your Message : " + this.message); } public void xmlInit() { System.out.println("xml configured initialize"); } public void xmlDestroy() { System.out.println("xml configured destroy"); } } 

#Bean.xml

       

当我使用scope="singleton"我的输出是:

  xml configured initialize Inside setMessage Your Message : My message xml configured destroy 

当我使用scope="prototype"我的输出是:

  xml configured initialize Inside setMessage Your Message : My message 

xmlDestroy()方法是用singleton范围bean调用的,但是没有prototype请帮助我以下,

它是否正确? 如果是这样,可能的原因是什么?

我也有一些疑问,

ApplicationContext , AbstractApplicationContext and ClassPathXmlApplicationContext之间的区别或关系是什么

使用单例范围bean调用xmlDestroy()方法,但不使用原型调用xmlDestroy()方法

Spring不管理原型bean的完整生命周期:容器实例化,配置,装饰和组装原型对象,将其交给客户端,然后不再了解该原型实例。 为了释放资源,尝试实现自定义bean后处理器。

与单个bean不同,弹簧容器管理整个生命周期

您可以查看此基本教程,了解不同上下文之间的差异

参考文档

单例bean意味着应用程序上下文中只有该bean的一个实例。 这意味着如果你做这样的事情:

 HelloSpring obj = (HelloSpring) context.getBean("helloSpring"); obj.setMessage("My message"); System.out.printIn(obj.getMessage()); HelloSpring anotherObj = (HelloSpring) context.getBean("helloSpring"); System.out.printIn(anotherObj.getMessage()); 

您将在控制台输出中看到“我的消息”两次。

对于原型bean,每次尝试从应用程序上下文中获取其中一个时,您将获得一个新实例,因此如果再次运行上述代码,则第二个控制台输出将为“null”。

因为容器不需要为原型bean调用destroy方法,所以它没有,并且行为是正确的。

这些类之间的区别在于它们分别是接口,抽象类和具体类,以便更好地理解这些概念,我建议在这里阅读Oracle Java Tutorials中的 java官方oracle文档。

这是预期的行为。 当你完成使用原型范围bean时,Spring无法知道,因此Spring不会为原型范围的bean管理bean销毁。 从文档:

尽管无论范围如何都在所有对象上调用初始化生命周期回调方法,但在原型的情况下,不会调用已配置的销毁生命周期回调。

有关更多信息,请参阅Spring文档 。

关于ApplicationContext ,您可以选择最适合您的应用程序的那个。 这取决于您是否要使用XML或注释bean配置,以及您是否在servlet容器中运行。 ApplicationContext本身是类型为heirarchy的根的接口。

你的应用程序可以每隔10毫秒询问一次原型bean的新实例,对bean做一些事情,然后让它超出范围。 如果Spring在应用程序关闭时必须销毁它们,那么它必须保持对每个创建的原型bean的引用,防止它们被垃圾收集,从而导致内存泄漏。

我还尝试获取bean的destroy事件,其范围是“prototype”。 所以我阅读了上面的所有答案并尝试了他们的答案。 结果,我发现即使是原型bean也无法检测到破坏。

尽管无论范围如何都在所有对象上调用初始化生命周期回调方法,但在原型的情况下,不会调用已配置的销毁生命周期回调。

请看这里( https://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/beans.html#beans-factory-scopes-prototype

请检查弹簧配置文件中的范围类型。 如果scope =“prototype”,则将其更改为scope =“singleton”