Java 什么时候调用 spring beans 破坏方法?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4460384/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 17:49:29  来源:igfitidea点击:

when is a spring beans destroy-method called?

javaspringjavabeansdestroy

提问by java_geek

I have put a sysout statement in the "destroy-method" for a bean. When i run a sample code, the sysout is not getting output. Does that mean the destroy-method is not getting called ?

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

The Test Class:

测试类:

  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();
    }
  }

The Bean

豆子

  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;
    }
  }

The Config file:

配置文件:

<?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>

采纳答案by skaffman

Your example doesn't work because you're not shutting down the appcontext, you're just letting the program terminate.

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

Call close()on the context, and you'll see the bean destroy-methods being called.

调用close()上下文,您将看到调用了 bean destroy-methods。

回答by Life

It may be too late for the OP, but if someone is still looking for it...

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

The close method is in AbstractApplicationContextand not ApplicationContext, also another way is to use ctx.registerShutdownHook()instead of ctx.close()for obvious reasons that while running Junits you might want to close the context but not while in production environment so let Spring decide on when to close it.

close 方法是 inAbstractApplicationContext和 not ApplicationContext,还有另一种方法是ctx.registerShutdownHook()instead of ctx.close()出于显而易见的原因使用Junits 时您可能希望关闭上下文,但在生产环境中则不想,因此让 Spring 决定何时关闭它。

回答by Doc Immortal

//Getting application context
ApplicationContext context = new ClassPathXmlApplicationContext(beansXML); 

//cleaning context
((ClassPathXmlApplicationContext) context).close(); 

回答by Abhishek Ramkumar

hi you need to change ApplicationContextto AbstractApplicationContextand then register to a ShutDownhookwhich will destroy your bean and also implement the DisposableBean interface eg:

嗨,您需要更改ApplicationContextAbstractApplicationContext然后注册到 a 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();
    }
  }

and now implemnt the DisposableBean interface

现在实现 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");
    }
  }

回答by dev

factory.destroySingletons();after your bean.display()as destroy-methodis valued in the bean definition. The default scope with which bean is created is singleton hence, invoking the factory.destroySingletons()will call the method mentioned in the destroy-method.

factory.destroySingletons();在您的bean.display()asdestroy-method在 bean 定义中被重视之后。创建 bean 的默认范围是单例,因此,调用factory.destroySingletons()will 调用destroy-method.

回答by Thushara Ariyasena

The "destroy-method" is only called if and only if the bean is a singleton instance

“销毁方法”仅当且仅当 bean 是单例实例时才被调用

See the log output of the IOC container

查看IOC容器的日志输出

INFO: Destroying singletonsin org.springframework.beans.factory.support.DefaultListableBeanFactory@1a0ce4c: defining beans [book1]; root of factory hierarchy

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