Depends-on in Spring

With this example I will show you how depends-on (@DependsOn annoattion) works in Spring application. Depends-on is basically used when you have a dependency on another bean without which you cannot proceed with the execution of your operations in current bean. Or if you need to initialize any bean before another bean, depends-on does this job. While creating bean you need to define depends-on attribute in bean. Here I will also show you how a bean depends on other multiple beans.

When a bean is typically dependent on another bean then we specify the dependent bean using @DependsOn annotation in Java based configuration metadata. However, sometimes dependencies between beans are less direct; for example, a static initializer that initializes something like loading of database driver in a class needs to be triggered first. The depends-on attribute can explicitly force one or more beans to be initialized before the bean using this element is initialized.

Prerequisites

Java at least 8, Spring Boot 2.4.0, Gradle 6.5.1 or Maven 3.6.3

Project Setup

You create either maven or gradle based project in your favorite tool or IDE. The name of the project is spring-depends-on-example.

For gradle based project you can use the following build.gradle script:

buildscript {
	ext {
		springBootVersion = '2.4.0'
	}
	
    repositories {
    	maven {
    		url 'https://plugins.gradle.org/m2/'
    	}
    }
    
    dependencies {
    	classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

plugins {
    id 'java-library'
    id 'org.springframework.boot' version "${springBootVersion}"
}

sourceCompatibility = 12
targetCompatibility = 12

repositories {
    mavenCentral()
    jcenter()
}

dependencies {
	implementation("org.springframework.boot:spring-boot-starter:${springBootVersion}")
}

For maven based project you can use the below pom.xml file:

<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.roytuts</groupId>
	<artifactId>spring-depends-on-example</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.4.0</version>
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>
	</dependencies>

    <build>
        <plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.8.1</version>
				<configuration>
					<source>at least 8</source>
					<target>at least 8</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

Spring Beans

Here I am going to create some beans and going to show you how to use depends-on using @DepensOn annotation. This annotation has to be placed on class level. You can pass multiple bean names if your bean has dependency on multiple beans. Bean name is determined from the class name with initial letter in lower case.

BeanB

This bean is dependent on other beans.

package com.roytuts.spring.depends.on.example;

import org.springframework.stereotype.Component;

@Component
public class BeanB {

    private String name;

    public BeanB() {
        System.out.println("BeanB is initialized.");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

BeanC

This bean depends on BeanB and will throw error if BeanB is not found. If your bean depends on a single bean then you don’t need to specify the bean name inside {} and can be specified simply @DependsOn(value = "beanB" ) or @DependsOn("beanB").

package com.roytuts.spring.depends.on.example;

import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;

@Component
@DependsOn(value = { "beanB" })
public class BeanC {

    public BeanC() {
        System.out.println("BeanC is initialized.");
    }

}

BeanA

This bean depends on multiple beans BeanB and BeanC.

package com.roytuts.spring.depends.on.example;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;

@Component
@DependsOn(value = { "beanB", "beanC" })
public class BeanA {

    @Autowired
    private BeanB beanB;

    public BeanA() {
        System.out.println("Initializing BeanA");
    }

    public BeanB getBeanB() {
        return beanB;
    }

    public void setBeanB(BeanB beanB) {
        this.beanB = beanB;
    }

}

Main Class

In Spring boot application you just need @SpringBootApplication and a main method in a class to start your application.

package com.roytuts.spring.depends.on.example;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringDependsOnApp implements CommandLineRunner {

    @Autowired
    private BeanA beanA;

    public static void main(String[] args) {
        SpringApplication.run(SpringDependsOnApp.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        beanA.getBeanB().setName("BeanB");

        System.out.println(beanA.getBeanB().getName());
    }

}

Testing the Application

Running the above main class, you will get below output:

BeanB is initialized.
BeanC is initialized.
Initializing BeanA
BeanB

Source Code

Download

Leave a Comment