In this article, we will see some examples of nested beans. A nested beans element has the ability to override the outer beans behavior. We will use nested beans to override lifecycle methods. We will also see how we can use it along with the spring profiles to completely override a bean definition.
This example uses the following frameworks:
Dependencies
Add the following dependencies:
spring-core
spring-context
Override the lifecycle methods using nested beans
In this example, we will override the lifecycle methods using nested beans. TestBean
contains different flavors of init
and destroy
methods. We will use one set for the default init
and destroy callbacks. We will use the other sets to override the lifecycle methods in our nested beans.
TestBean:
package com.javarticles.spring; public class TestBean { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public void init() { System.out.println("init() called"); } public void destroy() { System.out.println("destroy() called"); } public void init1() { System.out.println("init1() called"); } public void destroy1() { System.out.println("destroy1() called"); } public void init2() { System.out.println("init2() called"); } public void destroy2() { System.out.println("destroy2() called"); } public String toString() { return name == null ? "No Name" : name; } }
The main beans
element has default-init-method
and default-destroy-method
set to init
and destroy
methods.
We override it using nested beans to init1
and destroy1
. We have used one more level of nested beans to further override the behavior to call init2
and destroy2
.
nestedBeansContext.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.1.xsd" default-init-method="init" default-destroy-method="destroy" default-lazy-init="true"> <bean id="bean1" class="com.javarticles.spring.TestBean" /> <beans default-init-method="init1" default-destroy-method="destroy1"> <bean id="bean2" class="com.javarticles.spring.TestBean" /> <beans default-init-method="init2" default-destroy-method="destroy2"> <bean id="bean3" class="com.javarticles.spring.TestBean" /> </beans> <beans> <bean id="bean4" class="com.javarticles.spring.TestBean" /> </beans> </beans> </beans>
bean1
will use the default behavior set.bean2
‘s behavior is overridden. The default init and destroy methods areinit1
anddestroy1
.bean3
‘s behavior is again overridden. The default init and destroy methods areinit2
anddestroy2
.bean4
‘s uses the outer beans element’s default init and destroy methods and they areinit1
anddestroy1
.
SpringNestedBeansExample:
package com.javarticles.spring; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class SpringNestedBeansExample { public static void main(String[] args) { System.out.println("Nested beans Example"); ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( "nestedBeansContext.xml"); System.out.println("bean1's lifecycle methods will be the default init and destory methods"); verifyLifecycleMethods("bean1", context); System.out.println("bean2's lifecycle methods will be overriden by bean level init1 and destroy1 methods"); verifyLifecycleMethods("bean2", context); System.out.println("bean3's lifecycle methods will be overriden by nested beans init2 and destroy2 methods"); verifyLifecycleMethods("bean3", context); System.out.println("bean4's lifecycle methods will be the outer beans init1 and destroy1 methods"); verifyLifecycleMethods("bean4", context); } private static void verifyLifecycleMethods(String beanId, ConfigurableApplicationContext context) { Object bean = null; try { bean = context.getBean(beanId); } finally { context.getBeanFactory().destroyBean(beanId, bean); } } }
Output:
bean1's lifecycle methods will be the default init and destory methods init() called destroy() called bean2's lifecycle methods will be overriden by bean level init1 and destroy1 methods init1() called destroy1() called bean3's lifecycle methods will be overriden by nested beans init2 and destroy2 methods init2() called destroy2() called bean4's lifecycle methods will be the outer beans init1 and destroy1 methods init1() called destroy1() called
Override bean definition using nested beans
We may need certain beans when it is developer’s environment. We may also have to override certain beans for the developer environment to simplify testing.
In this example, we will override the bean definitions using nested beans and spring profiles.
Below context XML contains a nested beans element for dev profile. beanA
is of type TestBean
whereas in the dev profile it is just a plain string.
We also have an additional devOnlyBean
bean in dev profile.
nestedBeansWithProfileContext.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.1.xsd"> <bean id="beanA" class="com.javarticles.spring.TestBean"> <property name="name" value="Actual bean object"/> </bean> <beans profile="dev"> <bean name="beanA" class="java.lang.String"> <constructor-arg value="Simple string for dev"/> </bean> <bean name="devOnlyBean" class="java.lang.String"> <constructor-arg value="Only available for dev profile"/> </bean> </beans> </beans>
SpringNestedBeansProfileExample:
package com.javarticles.spring; import org.springframework.context.support.ClassPathXmlApplicationContext; public class SpringNestedBeansProfileExample { public static void main(String[] args) { System.out.println("Nested beans Profile Example"); System.setProperty("spring.profiles.active", "prod"); ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( "nestedBeansWithProfileContext.xml"); try { Object beanA = context.getBean("beanA"); System.out.println(beanA); System.out.println("Contains devOnlyBean? " + context.containsBean("devOnlyBean")); } finally { context.close(); } System.setProperty("spring.profiles.active", "dev"); System.out.println("Profile is set to dev, now spring should override the 'beanA' bean"); context = new ClassPathXmlApplicationContext( "nestedBeansWithProfileContext.xml"); try { Object beanA = context.getBean("beanA"); System.out.println(beanA); System.out.println("devOnlyBean is available only for dev profile"); System.out.println("Contains devOnlyBean? " + context.containsBean("devOnlyBean")); } finally { context.close(); } } }
Output:
Nested beans Profile Example Actual bean object Contains devOnlyBean? false Profile is set to dev, now spring should override the 'beanA' bean Simple string for dev devOnlyBean is available only for dev profile Contains devOnlyBean? true
Download the source code
This was an example about spring nested beans. You can download the source code here: springNestedBeansExample.zip