Java 何时调用SpringBeans销毁方法?

Java 何时调用SpringBeans销毁方法?,java,spring,javabeans,destroy,Java,Spring,Javabeans,Destroy,我在bean的“destroy方法”中放了一个sysout语句。当我运行一个示例代码时,sysout没有得到输出。这是否意味着没有调用destroy方法 测试类: package spring.test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public

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

测试类:

  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>

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


在上下文中调用
close()
,您将看到正在调用bean destroy方法。

对于OP来说可能已经太晚了,但是如果仍有人在寻找它


close方法在
AbstractApplicationContext
中,而不是
ApplicationContext
,另一种方法是使用
ctx.registerSutdownhook()
代替ctx.close()
很明显,在运行
Junit
s时,您可能希望关闭上下文,而不是在生产环境中,因此让Spring决定何时关闭它。

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

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

//cleaning context
((ClassPathXmlApplicationContext) context).close(); 
  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");
    }
  }

factory.DestroySingleton()bean.display()之后的代码>作为
destroy方法在bean定义中的值。创建bean的默认作用域是singleton,因此,调用
工厂。DestroySingleton()
将调用
销毁方法中提到的方法

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

请参阅IOC容器的日志输出


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

销毁方法工作正常。向我们展示你的代码和配置,就像你没有触发器让Spring知道你要关闭一样。正如其他人指出的,您需要让它知道,而不是关闭整个环境。如果您有太多的bean具有相同名称的初始化和/或销毁方法,则不需要在每个bean上声明init method和destroy method。使用默认的init方法,在元素上使用默认的destroy方法属性ApplicationContext上没有可用的close方法。java\u geek:它不在该接口上,而是在实现上:
ClassPathXmlApplicationContext
即使ClassPathXmlApplicationContext也没有close方法。@java\u geek:是的,它有。它在它的一个超类上。这很好,但是有没有办法让SpringJUnit4ClassRunner为你做这件事?我有几十个测试类在使用它,而类运行程序似乎并没有在测试完成后关闭上下文。这让人沮丧,因为当每个单独运行时,它们都是成功的,但当作为一个整体运行(通过mvn包)时,它们在运行了足够多的连接后失败,而没有正确关闭连接。请您添加更多详细信息或解释?您当前的答案非常稀疏,可能会被删除。+1。检查一下:有没有办法通过超时自动关闭它。假设我的应用程序在服务器上闲置了一周。它会在某个时候关闭吗?在这段时间内会调用destroy方法吗?@vsriram您可以创建自己的线程或runnable,通过在条件发生时调用ctx.close()来处理该问题。否则,只要您的服务器和jvm处于运行状态,它就不会被自己调用。这对我来说才是真正的答案。我正在努力理解为什么
close
registerShutdownHook
不起作用。这应该是公认的答案。当bean的类型是
prototype
时,我也在努力解决我的destroy方法没有被调用的问题。