4

I have a lot of singleton beans defined in my spring application context both different objects of the same type and objects of different types. To do some pre-destroy operations, I have implemented the DisposableBean interface for the bean classes. But, I would like to know how to destroy a bean with a particular id.

Here is my destroybean.xml

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

        <bean id="st" class="spring17.Student">
            <property name="sno" value="101"/>
            <property name="sname" value="Smith"/>
            <property name="age" value="20"/>
        </bean>

        <bean id="st1" class="spring17.Student">
            <property name="sno" value="102"/>
            <property name="sname" value="Scott"/>
            <property name="age" value="22"/>
        </bean>

</beans>

Here is my main class

package spring17;

import org.springframework.context.support.GenericXmlApplicationContext;

public class SpringPrg {
    @SuppressWarnings("resource")
    public static void main(String args[])
    {
        GenericXmlApplicationContext gc=new GenericXmlApplicationContext("classpath:destroybean.xml");

        Student st=gc.getBean("st",Student.class);

        System.out.println(st);

        gc.destroy();
    }
}

When i call the gc.destroy() st1 is also being destroyed which I don't want. You may suggest adding lazy-init attribute for st1 but it is not what I wanted.

Thanks in advance.

JavaTechnical
  • 8,846
  • 8
  • 61
  • 97
  • This should work: http://stackoverflow.com/questions/6855811/how-can-i-remove-a-singleton-spring-bean-from-applicationcontext – Emerson Farrugia Mar 30 '14 at 09:14
  • Could you tell me what exactly is bean destroying? – JavaTechnical Mar 30 '14 at 09:38
  • It basically means telling the container to stop holding a reference to a bean and cleaning up accordingly, under the assumption that the object will then get garbage collected. Though I can't think of a justifiable reason to do this. Using Spring means delegating bean lifecycle management to the container, and destroying beans manually violates that. – Emerson Farrugia Mar 30 '14 at 10:02
  • How could it be garbage collected if i am holding the reference in my program? – JavaTechnical Mar 30 '14 at 10:06
  • It can't. Why do you wan to destroy beans and still hold reference to them? – Emerson Farrugia Mar 30 '14 at 10:53
  • So, I should set `st=null` but, If i do so, automatically it will be garbage collected at some time, then why do I need `destroy()` again? – JavaTechnical Mar 30 '14 at 11:12
  • Huh? Forget garbage collection, it was a side note and orthogonal to your question. You call `close()` (not `destroy()`) on a `ConfigurableApplicationContext` (in a non-webapp environment) to release resources when you're done with Spring. `destroy()` is meant as an internal callback for beans which have resources to free up. But you haven't answered the most important question here. Why are you trying to selectively destroy some beans in the container and not all of them? – Emerson Farrugia Mar 30 '14 at 11:33
  • Releasing the resources in the sense, leaving no references to the objects created by the container (like `st`) so that they will be garbage collected? – JavaTechnical Mar 30 '14 at 12:09

2 Answers2

3

As others have suggested, you need to get a reference to the BeanFactory which the ApplicationContext uses, cast it to a DefaultListableBeanFactory and invoke the destroySingleton(..) method

Student st = gc.getBean("st", Student.class);
((DefaultListableBeanFactory) gc.getBeanFactory()).destroySingleton("st");

The underlying DefaultListableBeanFactory keeps a reference to your singleton beans. The call to destroySingleton(..) will remove all references to the specified bean and call any DisposableBean or other registered Spring-managed finalizers on it.

However, your program has another reference to the instance in the variable st. So you also need to clear that reference if you want the instance to be garbage collected.

st = null;
Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
3

But, I would like to know how to destroy a bean with a particular id.

This seems to me to be an invalid question. The spring context is designed to be initialized and destroyed all at once. The idea that you would destroy just one of the wired beans that may be still in use by other beans seems to be dangerous indeed. There is no way that I know of, aside from some hackery, to get spring to forget about one of the beans wired into the collection.

If you want beans to be dynamic then I would have some sort of StudentManager bean instead. This manager would maintain its own collection of Student objects. These students would not be wired via Spring but the manager would be. You could then create and destroy Student objects at will without creating possible wiring problems.

Gray
  • 115,027
  • 24
  • 293
  • 354