Spring bean destroy-method,singleton和prototype范围

时间:2013-02-23 12:15:16

标签: java spring scope

我是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

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

     <bean id="helloSpring" class="test.spring.HelloSpring" 
          scope="prototype" init-method="xmlInit" destroy-method="xmlDestroy">

     </bean>
     </beans>

当我拿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()范围bean调用

singleton方法,但不使用prototype 请帮助我以下,

这是对的吗?如果是这样,可能的原因是什么?

我也有一些问题,如

什么是差异或关系 ApplicationContext , AbstractApplicationContext and ClassPathXmlApplicationContext

6 个答案:

答案 0 :(得分:38)

使用单例范围bean调用

xmlDestroy()方法,但不使用原型,因为

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

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

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

参考documentation

答案 1 :(得分:2)

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

  

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

有关详细信息,请参阅Spring documentation

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

答案 2 :(得分:2)

单例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方法,所以它没有,并且行为是正确的。

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

答案 3 :(得分:2)

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

答案 4 :(得分:0)

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

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

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

答案 5 :(得分:-2)

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

<bean id="helloWorld" class="com.example.test.HelloWorld"
init-method="init" destroy-method="destroy">
<property name="message" value="Hello World!" />