【问题标题】:when is a spring beans destroy-method called?什么时候调用 spring beans 销毁方法?
【发布时间】:2011-05-26 12:19:26
【问题描述】:

我在 bean 的“destroy-method”中添加了一条 sysout 语句。当我运行示例代码时,sysout 没有得到输出。这是否意味着销毁方法没有被调用?

测试类:

  package spring.test;

  import org.springframework.context.ApplicationContext;
  import org.springframework.context.support.ClassPathXmlApplicationContext;

  public class InitTest {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("InitTestContext.xml");
        InitTestBean bean = (InitTestBean)ctx.getBean("InitTestBean");
        bean.display();
    }
  }

豆子

  package spring.test;

  public class InitTestBean {
    private String prop1;
    private String prop2;

    public InitTestBean(String prop1, String prop2) {
        System.out.println("Instantiating InitTestBean");
        this.prop1 = prop1;
        this.prop2 = prop2;
    }

    public void setProp1(String prop1) {
        System.out.println("In setProp1");
        this.prop1 = prop1;
    }

    public void setProp2(String prop2) {
        System.out.println("In setProp2");
        this.prop2 = prop2;
    }

    public String getProp1() {
        return prop1;
    }

    public String getProp2() {
        return prop2;
    }

    public void display() {
        System.out.println("Prop1 is " + prop1);
        System.out.println("Prop2 is " + prop2);
    }

    public void initialize(){
        System.out.println("In initialize");
        this.prop1 = "init-prop1";
        this.prop2 = "init-prop2";
    }

    public void teardown() {
        System.out.println("In teardown");
        this.prop1 = null;
        this.prop2 = null;
    }
  }

配置文件:

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

    <bean id="InitTestBean" class="spring.test.InitTestBean" init-method="initialize" destroy-method="teardown">
        <constructor-arg value="Prop1" />
        <constructor-arg value="Prop2" />
        <property name="prop1" value="setProp1"/>
        <property name="prop2" value="setProp2"/>
    </bean>

</beans>

【问题讨论】:

  • destroy-method 工作得很好。向我们展示您的代码和配置。
  • 应该是this
  • 你没有触发让 Spring 知道你正在关闭。正如其他人指出的那样,您需要让它知道而不是关闭整个环境。
  • 如果您有太多具有相同名称的初始化和/或销毁方法的 bean,则无需在每个单独的 bean 上声明 init-method 和 destroy-method。在 元素上使用 default-init-method, default-destroy-method 属性

标签: java spring javabeans destroy


【解决方案1】:

factory.destroySingletons();bean.display() 之后,因为 destroy-method 在 bean 定义中被赋值。创建 bean 的默认作用域是单例,因此,调用 factory.destroySingletons() 将调用 destroy-method 中提到的方法。

【讨论】:

  • 您能补充更多细节或解释吗?您当前的答案非常稀疏,很可能会被删除。
【解决方案2】:

只有当且仅当 bean 是单例实例时才会调用“destroy-method”

查看IOC容器的日志输出

INFO:销毁单例 in org.springframework.beans.factory.support.DefaultListableBeanFactory@1a0ce4c:定义bean [book1];工厂层次结构的根

【讨论】:

  • 这对我来说是真正的答案。我很难理解为什么 closeregisterShutdownHook 不起作用。
  • 这应该是公认的答案。当 bean 的类型为 prototype 时,我也正在努力解决未调用的 destroy 方法。
【解决方案3】:

您好,您需要将ApplicationContext 更改为AbstractApplicationContext,然后注册到ShutDownhook,这将破坏您的bean 并实现DisposableBean 接口,例如:

  package spring.test;

  import org.springframework.context.ApplicationContext;
  import org.springframework.context.support.ClassPathXmlApplicationContext;
  import org.springframework.context.support.AbstractApplicationContext;
  public class InitTest {
    public static void main(String[] args) {
       AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("InitTestContext.xml");
  ctx.registerShutdownHook();
        InitTestBean bean = (InitTestBean)ctx.getBean("InitTestBean");
        bean.display();
    }
  }

现在实现 DisposableBean 接口

package spring.test;
import org.springframework.beans.factory.DisposableBean;
  public class InitTestBean implements DisposableBean{
    private String prop1;
    private String prop2;
    public InitTestBean(String prop1, String prop2) {
        System.out.println("Instantiating InitTestBean");
        this.prop1 = prop1;
        this.prop2 = prop2;
    }
    public void setProp1(String prop1) {
        System.out.println("In setProp1");
        this.prop1 = prop1;
    }
    public void setProp2(String prop2) {
        System.out.println("In setProp2");
        this.prop2 = prop2;
    }
    public String getProp1() {
        return prop1;
    }
    public String getProp2() {
        return prop2;
    }
    public void display() {
        System.out.println("Prop1 is " + prop1);
        System.out.println("Prop2 is " + prop2);
    }
    public void initialize(){
        System.out.println("In initialize");
        this.prop1 = "init-prop1";
        this.prop2 = "init-prop2";
    }
    public void teardown() {
        System.out.println("In teardown");
        this.prop1 = null;
        this.prop2 = null;
    }
    @Override
    public void destroy() throws Exception {

        System.out.println(" the bean has been destroyed");
    }
  }

【讨论】:

    【解决方案4】:
    //Getting application context
    ApplicationContext context = new ClassPathXmlApplicationContext(beansXML); 
    
    //cleaning context
    ((ClassPathXmlApplicationContext) context).close(); 
    

    【讨论】:

      【解决方案5】:

      对于 OP 来说可能为时已晚,但如果有人还在寻找它...

      close 方法是在AbstractApplicationContext 而不是ApplicationContext,还有另一种方法是使用ctx.registerShutdownHook() instead of ctx.close(),原因很明显,在运行Junits 时,您可能想要关闭上下文,但在生产环境,所以让 Spring 决定何时关闭它。

      【讨论】:

      • 有没有办法通过超时自动关闭它。假设我已将我的应用程序在我的服务器中闲置了一周。它会在某个时候关闭吗?在这段时间内会调用destroy方法吗?
      • @vsriram 您可以创建自己的线程或可运行的线程,通过在您的条件发生时调用 ctx.close() 来处理该问题。否则,只要你的服务器和jvm启动,它就不会被自己调用
      【解决方案6】:

      您的示例不起作用,因为您没有关闭 appcontext,您只是让程序终止。

      在上下文中调用close(),你会看到bean destroy-methods被调用。

      【讨论】:

      • ApplicationContext 上没有可用的关闭方法。
      • java_geek:不在那个接口上,在实现上:ClassPathXmlApplicationContext
      • 甚至classpathxmlapplicationcontext也没有close方法。
      • @java_geek:是的,确实如此。它在它的一个超类中。
      • 这很好,但是有没有办法让 SpringJUnit4ClassRunner 为你做这件事?我有几十个使用这个的测试类,并且类运行器在完成测试后似乎没有关闭上下文。这令人沮丧,因为当每个单独运行时它们是成功的,但是当作为一个整体运行时(通过 mvn 包),它们在运行足够多而没有正确关闭连接后会失败。
      猜你喜欢
      • 2023-03-31
      • 1970-01-01
      • 2016-05-25
      • 1970-01-01
      • 1970-01-01
      • 2010-10-12
      • 1970-01-01
      • 2019-12-09
      • 1970-01-01
      相关资源
      最近更新 更多