If one bean has a dependency on another bean then generally in Spring framework we configure it to be set as a property
of another. Typically you accomplish this with the <ref/> element in XML-based configuration metadata or using @Autowired annotation.
However, sometimes dependencies between beans may not be direct but you may still want to ensure that a specific bean is
initialized before another bean. For example in one bean there is a static block which has to be executed before another bean is initialized. In Spring you can use depends-on
attribute in XML configuration or @DependsOn
annotation to explicitly force one or more beans to be initialized before the bean using this element is initialized.
Spring depends-on attribute example
In the example there is a class ClassB and another class ClassA which has a static block. You want to ensure that ClassA is initialized first and its static block executed before ClassB is initialized even thought ClassB has no direct dependency on ClassA.
public class ClassA { ClassA(){ System.out.println("In constructor of ClassA"); } //static block static { System.out.println("in static block ClassA"); System.out.println("Register DB Driver as a one time activity"); } }
public class ClassB { ClassB(){ System.out.println("In constructor of ClassB"); } }Configuration
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="beanA" class="com.knpcode.springbeans.ClassA" /> <bean id="beanB" class="com.knpcode.springbeans.ClassB" depends-on="beanA"> </bean> </beans>
In the configuration there is a bean definition for ClassA and ClassB as you can see there is no direct dependency on beanA in beanB so depends-on attribute is used to enforce that beanA is initialized before beanB.
You can use the following class with main method to read the configuration and access beans.
public class App { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("appcontext.xml"); ClassB obj = context.getBean("beanB", ClassB.class); context.close(); } }Output
10:26:02.631 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'beanA' in static block ClassA Register DB Driver as a one time activity In constructor of ClassA 10:26:02.683 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'beanB' In constructor of ClassB
As you can see from the output beanA is initialized first.
Using depends-on with multiple beans
If there is a dependency on multiple beans, supply a list of bean names as the value of the depends-on attribute (commas, whitespace, and semicolons are valid delimiters).
<bean id="beanA" class="com.knpcode.springbeans.ClassA" /> <bean id="beanB" class="com.knpcode.springbeans.ClassB" /> <bean id="beanC" class="com.knpcode.springbeans.ClassC" depends-on="beanA,beanB"> </bean>
Spring @DependsOn annotation example
If you are using Spring Java configuration or annotation to scan components then you can use @DependsOn annotation in Spring to explicitly force one or more beans to be initialized first. This annotation may be used directly on any class or indirectly annotated with Component or on methods annotated with Bean.
Following example shows the use of @DependsOn annotation where Spring Java configuration is used so @DependsOn annotation is used along with @Bean annotation.
public class ClassA { public ClassA(){ System.out.println("In constructor of ClassA"); } //static block static { System.out.println("in static block ClassA"); System.out.println("Register DB Driver as a one time activity"); } }
public class ClassB { public ClassB(){ System.out.println("In constructor of ClassB"); } }
public class ClassC { public ClassC(){ System.out.println("In constructor of ClassC"); } }Java configuration class
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.DependsOn; import com.knpcode.springbeans.ClassA; import com.knpcode.springbeans.ClassB; import com.knpcode.springbeans.ClassC; @Configuration public class AppConfig { @Bean @DependsOn({"beanA","beanB"}) public ClassC beanC() { return new ClassC(); } @Bean public ClassB beanB() { return new ClassB(); } @Bean public ClassA beanA() { return new ClassA(); } }
In the configuration there is a bean definition for ClassA, ClassB and ClassC. To enforce that beanA and beanB are initialized before beanC, @DependsOn annotation is used on bean definition of ClassC with beanA and beanB as values.
For running the application you can use the following class.
public class App { public static void main(String[] args) { AbstractApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); ClassC obj = context.getBean("beanC", ClassC.class); context.close(); } }Output
10:52:01.160 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'beanA' in static block ClassA Register DB Driver as a one time activity In constructor of ClassA 10:52:01.293 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'beanB' In constructor of ClassB 10:52:01.297 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'beanC' In constructor of ClassC
As you can see from the output beanA and beanB are initialized first.
That's all for the topic Spring depends-on Attribute and @DependsOn Annotation. If something is missing or you have something to share about the topic please write a comment.
You may also like
- Spring IoC Container Types – ApplicationContext and BeanFactory
- Injecting Prototype Bean into a Singleton Bean in Spring
- Fix LazyInitializationException: could not initialize proxy Error
- UEFI Compatibilty for Ubuntu Installation
- Comparable Vs Comparator in Java
- Semaphore in Java With Examples
- Java String length() Method With Examples
- How to Read And Write Parquet File in Hadoop
No comments:
Post a Comment