【问题标题】:How Inner bean is destroyed in Spring?Spring中如何销毁Inner bean?
【发布时间】:2014-02-03 12:36:40
【问题描述】:

当一个 bean 被声明为内部 bean 时,它应该随着外部 bean 的销毁而被销毁。但是在下面没有调用 bean 的销毁方法的情况下不会发生这种情况。

innerbeans-spring.xml

<bean id="car" name="carBean" class="com.semanticbits.shoaib.innerbeans.Car" destroy-method="destroy" init-method="init">
    <property name="engine">
        <bean class="com.semanticbits.shoaib.innerbeans.Engine" destroy-method="destroy" init-method="init">

        </bean>
    </property>
</bean>

Car.java:这里只需要编写代码

 public void init(){
    System.out.println("Car init method");
 }
 public void destroy(){
    System.out.println("Car destroy method");
 }


  public static void main(String[] args){
    ConfigurableApplicationContext context=(ConfigurableApplicationContext)ApplicationContextFactory.getApplicationContext("innerbeans-spring.xml");
    Car car=context.getBean("car",Car.class);
    context.getBeanFactory().destroyBean("car",car);
}

Engine.java:这里只需要编写代码

public void init(){
    System.out.println("Engine init method");
}

public void destroy(){
    System.out.println("Engine destroy method");
}

输出:

Engine init method
Car init method
Car destroy method

我的问题是:

1) getBeanFactory().destroyBean(String beanName,Object beanReference) beanName 在这里是什么意思?

2) 为什么 Engine 类的 destroy 方法不被调用,因为 Engine 是 Car 类的内部 bean??

扩展问题:

public static void main(String[] args){
   ConfigurableApplicationContext context=(ConfigurableApplicationContext)ApplicationContextFactory.getApplicationContext("innerbeans-spring.xml");
   Car car=context.getBean("car",Car.class);
   context.getBeanFactory().destroyBean("car",car);
   //now here Car bean is destroy.
   //when I call then check the output section.

   context.getBeanFactory().destroySingletons();


}

扩展输出:

Engine init method
Car init method
Car destroy method
Car destroy method
Engine destroyed.

3)当 Car 实例已经被销毁时,为什么要再次调用 Car 的 destroy() 方法?

提前致谢。

【问题讨论】:

  • 如果需要额外的代码,请告诉我。
  • 既然没有提到Engine bean,那不就是说Engine bean 被破坏了吗?垃圾会收集任何内部类,Car bean 的变量。
  • 那么为什么Engine类没有调用destroy()方法

标签: java spring inversion-of-control


【解决方案1】:

如果我没记错的话,我相信只有在 BeanFactory 关闭时,Engine 才会被销毁。

你也可以直接让 Car 处理这个,通过调用 Engine 的 destroy 方法:

Car.java:

public void destroy(){
    engine.destroy();
    System.out.println("Car destroy method");
}

【讨论】:

  • 为什么要显式调用 engine.destroy()...如果外部 bean 被垃圾回收,那么内部 bean 应该自动被垃圾回收。我正在销毁汽车引用,该引用应该间接销毁引擎,从而调用销毁回调方法。
  • 因为垃圾回收不会调用你的destroy方法......而destroy方法通常包含你希望看到执行的“清理代码”。
【解决方案2】:

您有一个beanengine 声明

<bean class="com.semanticbits.shoaib.innerbeans.Engine" destroy-method="destroy" init-method="init">
</bean>

这意味着 Spring 引用了这个 bean 定义和它创建的实例(它注入)。当您决定关闭/关闭 ApplicationContext 时,Spring 会遍历每个 bean,并在需要时调用它们的 destroy-method

但是,您只是在破坏 car bean。 engine bean 的生命周期与 car bean 无关。 engine bean 是 ApplicationContext 的一部分,即使它是在另一个 bean 定义中定义的。

【讨论】:

  • 如果我调用 context.getBeanFactory().destroySingletons(); 你现在能告诉我吗?在我上面写的所有代码之后,应该输出什么。
  • 除了上述输出之外,它还给出了 Car destroy 方法 Engine Destroy 方法...如果 Car 已经被销毁,为什么还要再次销毁汽车?
  • 请看我更新的代码。一旦 Car bean 被销毁,为什么又要调用 destroy 方法,这是相当混乱的。
  • @shoaib destroyBean 方法旨在与上下文不再引用的原型 bean 一起使用。尝试拨打destroySingletons 两次。在第一次调用之后,上下文会删除对其拥有的 bean 的所有引用。
  • @ShoaibChikate 不,Car 的 bean 定义使其成为单通。然而,destroyBean 方法并没有摆脱来自ApplicationContext 的对该实例的引用,特别是因为该方法旨在与ApplicationContext 没有任何引用的原型bean 一起使用。该方法只是为了调用destroy-method
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-13
  • 1970-01-01
  • 2012-05-14
  • 2013-02-22
相关资源
最近更新 更多