Bean Life Cycle Management



Hooking into Bean Creation



Specifying an Initialization Method


one way to receive the initialization callback is to designate a method on your bean as an initialization method and tell Spring to use this method as an initialization method.

Specifying a callback method is simply a case of specifying the name in the init-method attribute of a bean’s <bean> tag

The SimpleBean Class

public class SimpleBean {
private static final String DEFAULT_NAME = "Jan Machacek";
private String name;
private int age = 0;
public void init() {
System.out.println("initializing bean");
if (this.name == null) {
System.out.println("No name specified, using default.");
this.name = DEFAULT_NAME;
}
if (this.age == 0) {
throw new IllegalArgumentException("You must set the [age] property " +➥
"bean of type [" + getClass().getName() + "]");
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("SimpleBean");
sb.append("{name='").append(name).append('\'');
sb.append(", age=").append(age);
sb.append('}');
return sb.toString();
}
}

Notice that we have defined a method, init(), to act as the initialization callback. The init() method checks to see if the name property has been set, and if it has not, it uses the default value stored in the DEFAULT_VALUE constant. The init() method also checks to see if the age property is set and throws an IllegalArgumentException if it is not.

The main() method of the SimpleBeanDemo class attempts to obtain three beans from the BeanFactory, all of type SimpleBean, using its own getBean() method. Notice that in the getBean() method, if the bean is obtained successfully, its details are written to stdout. If an exception is thrown in the init() method, as will occur in this case if the age property is not set, Spring wraps that exception in a BeanCreationException. The getBean() method catches these exceptions and writes amessage to stdout informing us of the error.

Configuring the Simple Beans

<?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.xsd">
<bean id="simple1" class="com.apress.prospring2.ch04.lifecycle.SimpleBean" init-method="init">
<property name="age" value="29"/>
<property name="name" value="Dr. Jekyll"/>
</bean>
<bean id="simple2" class="com.apress.prospring2.ch04.lifecycle.SimpleBean" init-method="init">
<property name="age" value="29"/>
</bean>
<bean id="simple3" class="com.apress.prospring2.ch04.lifecycle.SimpleBean" init-method="init">
<property name="name" value="Mr. Hyde"/>
</bean>
</beans>


Implementing the InitializingBean Interface


The InitializingBean interface defined in Spring allows you to define, inside your bean code, that you want the bean to receive notification that Spring has finished configuring it. Just like when you are using an initialization method, this gives you the opportunity to check the bean configuration to ensure that it is valid, providing any default values along the way.

The InitializingBean interface defines a single method, afterPropertiesSet(), that serves the same purpose as the init() method

public class SimpleBeanIB implements InitializingBean {
private static final String DEFAULT_NAME = "Jan Machacek";
private String name;
private int age = 0;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("SimpleBean");
sb.append("{name='").append(name).append('\'');
sb.append(", age=").append(age);
sb.append('}');
return sb.toString();
}
public void afterPropertiesSet() throws Exception {
System.out.println("initializing bean");
if (this.name == null) {
System.out.println("No name specified, using default.");
this.name = DEFAULT_NAME;
}
if (this.age == 0) {
throw new IllegalArgumentException("You must set the [age] property “ +
"bean of type [" + getClass().getName() + "]");
}
}
}


Hooking into Bean Destruction
When using a BeanFactory implementation that implements the ConfigurableListableBeanFactory interface (such as XmlBeanFactory), you can signal the BeanFactory that you want to destroy all singleton instances with a call to destroySingletons().


Executing a Method When a Bean Is Destroyed

To designate a method to be called when a bean is destroyed, you simply specify the name of the method in the destroy-method attribute of the bean’s <bean> tag.

Using a destroy-method Callback

public class DestructiveBean implements InitializingBean {
public class DestructiveBean {
private InputStream is = null;
private String filePath = null;
public void afterPropertiesSet() throws Exception {
System.out.println("Initializing Bean");
Assert.notNull(this.filePath, "The [filePath] property of [" +
getClass().getName() + "] must be set.");
new File(this.filePath).createNewFile();
this.is = new FileInputStream(this.filePath);
}
public void destroy() {

System.out.println("Destroying Bean");
if (this.is != null) {
try {
this.is.close();
this.is = null;
new File(this.filePath).delete();
} catch (IOException ex) {
System.err.println("WARN: An IOException occured"
+ " while trying to close the InputStream");
}
}
}
public void setFilePath(String filePath) {
this.filePath = filePath;
}

}

Sample Application for the destroySingletons() Call

public class DestructiveBeanDemo {
public static void main(String[] args) {
System.out.println(factory.getBean("destructive"));
factory.destroySingletons();
System.out.println("Almost done!");
new BufferedInputStream(System.in).read();
}

}

Configuring a destroy-method Callback

<?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.xsd">
<bean id="destructive"
class="com.apress.prospring2.ch04.lifecycle.DestructiveBean" destroy-method="destroy">
<property name="filePath" value="/tmp/prospring25"/>
</bean>

</beans>


Implementing the DisposableBean Interface


As with initialization callbacks, Spring provides an interface, in this case DisposableBean, that you can implement in your beans as an alternative mechanism for receiving destruction callbacks. The DisposableBean interface defines a single method, destroy(), that is called just before the bean is destroyed. Using this mechanism is orthogonal to using the InitializingBean interface to receive initialization callbacks.

Implementing DisposableBean

public class DestructiveBeanI implements InitializingBean, DisposableBean {
private InputStream is = null;
private String filePath = null;
public void afterPropertiesSet() throws Exception {
System.out.println("Initializing Bean");
Assert.notNull(this.filePath, "The [filePath] property of [" +

getClass().getName() + "] must be set.");
new File(this.filePath).createNewFile();
this.is = new FileInputStream(this.filePath);
}
public void destroy() {
System.out.println("Destroying Bean");
if (this.is != null) {
try {
this.is.close();
this.is = null;
new File(this.filePath).delete();
} catch (IOException ex) {
System.err.println("WARN: An IOException occured"
+ " while trying to close the InputStream");
}
}
}
public void setFilePath(String filePath) {
this.filePath = filePath;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("DestructiveBean");
sb.append("{is=").append(is);
sb.append(", filePath='").append(filePath).append('\'');
sb.append('}');
return sb.toString();
}

}

Configuration Using the DisposableBean Interface

<?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.xsd">
<bean id="destructive"
class="com.apress.prospring2.ch04.lifecycle.DestructiveBean">
<property name="filePath" value="/tmp/prospring25"/>

</bean>

</beans>

Leave a Reply

Subscribe to Posts | Subscribe to Comments

About This Site

Howdy! My name is Suersh Rohan and I am the developer and maintainer of this blog. It mainly consists of my thoughts and opinions on the technologies I learn,use and develop with.

Blog Archive

Powered by Blogger.

- Copyright © My Code Snapshots -Metrominimalist- Powered by Blogger - Designed by Suresh Rohan -