Java 何时调用SpringBeans销毁方法?
我在bean的“destroy方法”中放了一个sysout语句。当我运行一个示例代码时,sysout没有得到输出。这是否意味着没有调用destroy方法 测试类: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
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方法没有被调用的问题。