In this article, we will show you how one can be notified when a component, alias and an import context is registered during a bean definition reading process.
Dependencies
Add the following dependencies:
spring-core
spring-context
spring-beans
pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.javarticles.jdbc.datasource</groupId> <artifactId>springdatasource</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${spring.version}</version> </dependency> </dependencies> <properties> <spring.version>3.2.3.RELEASE</spring.version> </properties> </project>
Sample Bean
Our sample bean consists of an inner bean which is of the same type and a string value. It also has myInit()
and myDestroy()
to be called as the container instantiates or destroys the bean.
TestBean:
package com.javarticles.spring; public class TestBean { private TestBean innerBean; private String value; public TestBean(){} public TestBean(String value) { this.value = value; } public String getValue() { return value; } public TestBean getInnerBean() { return innerBean; } public void setValue(String value) { this.value = value; } public void myDestroy() { System.out.println("myDestroy called for TestBean(" + value + ")"); } public void myInit() { System.out.println("myInit called for TestBean(" + value + ")"); } public void setInnerBean(TestBean innerBean) { this.innerBean = innerBean; } }
Application Context
applicationContext.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.xsd" default-lazy-init="true" default-autowire="constructor" default-init-method="myInit" default-destroy-method="myDestroy" default-merge="true"> <import resource="importContext.xml" /> <alias name="testBean" alias="alias1" /> <alias name="testBean" alias="alias2" /> <bean id="testBean" class="com.javarticles.spring.TestBean"> <constructor-arg type="java.lang.String" value="A" /> <property name="innerBean"> <ref bean="testBean2" /> </property> </bean> <bean id="testBean2" class="com.javarticles.spring.TestBean"> <property name="value" value="C" /> <property name="innerBean"> <bean class="com.javarticles.spring.TestBean"> <property name="value" value="D" /> </bean> </property> </bean> </beans>
importContext.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.xsd" default-lazy-init="true" default-autowire="byType" default-init-method="myInit" default-destroy-method="myDestroy" default-merge="false"> <bean id="testBean3" class="com.javarticles.spring.TestBean"> <property name="value" value="E"/> </bean> </beans>
Custom ReaderEventListener
MyReaderEventListener:
package com.javarticles.spring; import org.springframework.beans.factory.parsing.AliasDefinition; import org.springframework.beans.factory.parsing.ComponentDefinition; import org.springframework.beans.factory.parsing.DefaultsDefinition; import org.springframework.beans.factory.parsing.ImportDefinition; import org.springframework.beans.factory.parsing.ReaderEventListener; import org.springframework.beans.factory.xml.DocumentDefaultsDefinition; public class MyReaderEventListener implements ReaderEventListener { public void defaultsRegistered(DefaultsDefinition defaultsDefinition) { DocumentDefaultsDefinition defaults = (DocumentDefaultsDefinition) defaultsDefinition; System.out.println("Default attributes registered: " + "autowire: " + defaults.getAutowire() + ", " + "autowire-candidats: " + defaults.getAutowireCandidates() + ", " + "destroy-method: " + defaults.getDestroyMethod() + ", " + "init-method: " + defaults.getInitMethod() + ", " + "lazy-init: " + defaults.getLazyInit() + ", " + "merge: " + defaults.getMerge()); } public void componentRegistered(ComponentDefinition componentDefinition) { System.out.println("Component Registered: " + componentDefinition.getName()); } public void aliasRegistered(AliasDefinition aliasDefinition) { System.out.println("Alias Registered: " + aliasDefinition.getAlias()); } public void importProcessed(ImportDefinition importDefinition) { System.out.println("Import processed: " + importDefinition.getImportedResource()); } }
Event Publication Example
- Create the bean factory.
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
- Create XML reader.You need to pass the above bean factory so that the beans get registered as they are parsed.
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
- Create
ReadEventListener
and set it to the reader.ReaderEventListener eventListener = new MyReaderEventListener(); reader.setEventListener(eventListener);
- Load the context.
reader.loadBeanDefinitions("applicationContext.xml");
- Get
testBean
.TestBean testBean = (TestBean) beanFactory.getBean("testBean");
- Destroy the
testBean
.beanFactory.destroyBean("testBean", testBean);
EventPublicationExample:
package com.javarticles.spring; import org.springframework.beans.factory.parsing.ReaderEventListener; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; public class EventPublicationExample { public static void main(String[] args) { DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory); ReaderEventListener eventListener = new MyReaderEventListener(); reader.setEventListener(eventListener); reader.loadBeanDefinitions("applicationContext.xml"); TestBean testBean = (TestBean) beanFactory.getBean("testBean"); beanFactory.destroyBean("testBean", testBean); } }
Output:
May 13, 2015 5:24:59 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions INFO: Loading XML bean definitions from class path resource [applicationContext.xml] Default attributes registered: autowire: constructor, autowire-candidats: null, destroy-method: myDestroy, init-method: myInit, lazy-init: true, merge: true May 13, 2015 5:25:00 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions INFO: Loading XML bean definitions from class path resource [importContext.xml] Default attributes registered: autowire: byType, autowire-candidats: null, destroy-method: myDestroy, init-method: myInit, lazy-init: true, merge: false Component Registered: testBean3 Import processed: importContext.xml Alias Registered: alias1 Alias Registered: alias2 Component Registered: testBean Component Registered: testBean2 myInit called for TestBean(D) myInit called for TestBean(C) myInit called for TestBean(A) myDestroy called for TestBean(A)
Download the source code
This was an example about custom ReadEventListener
. You can download the source code here: springEventPublicationExample.zip