Spring @ConditionalOnBean Example

Conditional On Bean

I will create examples on Spring @ConditionalOnBean. Anywhere you define a Spring bean, you can optionally add a condition. Only if the specified condition is satisfied then only bean will be added to the application context. To declare a condition, you can use any of the @Conditional… annotations. The @ConditionalOnBean annotation let a bean be included based on the presence of specific beans. By default Spring will search entire hierarchy (SearchStrategy.ALL).

Prerequisites

Java 12/19, Maven 3.6.3/3.8.5, Spring Boot 2.1.7 – 2.4.5/3.1.5

Project Setup

Create a maven based project in your favorite IDE or tool with the project name as spring-conditional-on-bean.

I will update the build file (pom.xml) as follows to include the spring boot dependencies.

<?xml version="1.0" encoding="UTF-8"?>

<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-conditional-on-bean</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<maven.compiler.source>19</maven.compiler.source>
		<maven.compiler.target>19</maven.compiler.target>
	</properties>

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

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

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>

Service Class

I will create simple service class without any methods in it. Ideally this service class will have some methods to perform your project’s business operations.

public class SpringService {

}

Examples on @ConditionalOnBean

I will create various ways of using @ConditionalOnBean annotation on the bean.

Simple Beans

I will create two beans which will be required to call on @ConditionalOnBean annotation because these annotated bean will be executed only when the required bean is found.

Bean – RequiredBean

I have used annotation @Component to get advantage of autowire.

@Component
public class RequiredBean {

}

Bean – AnotherRequiredBean

@Component
public class AnotherRequiredBean {

}

Examples – @ConditionalOnBean

I will create a Spring Config class and use annotation @ConditionalOnBean in various ways, such as, by name, type, value, search and will see how it works.

I will modify our Spring Config class for each type of example.

I will also create a main class to run our application. The source of the main class is given below. I will not modify the main class but I will run our main class after each modification to the Spring Config class.

@SpringBootApplication
public class SpringConditionalOnBeanApp implements CommandLineRunner {

	@Autowired
	private SpringService springService;

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

	@Override
	public void run(String... args) throws Exception {
		System.out.println("Spring service fully qualified class name: " + springService.getClass());
	}
}

@ConditionalOnBean – by value

Here I will show @ConditionalOnBean by value in Spring Config class.

I will pass the class for the value value.

@Configuration
public class SpringConfig {

	@Bean
	@ConditionalOnBean(value = RequiredBean.class)
	public SpringService springService() {
		return new SpringService();
	}

}

Run the main class to see the result as shown below in the console.

Spring service fully qualified class name: class com.roytuts.spring.conditional.on.bean.SpringService

Therefore to build a new instance of the SpringService class your RequiredBean class must exist.

@ConditionalOnBean – by name

I will now use by passing the bean name for the value name. Here I am passing single bean names but you can also pass multiple bean names and I will show on this after this example.

As I have annotated class RequiredBean with @Component and by default bean name is resolved as class name with initial letter in lower case, so you don’t need to define it separately.

@Configuration
public class SpringConfig {

	@Bean
	@ConditionalOnBean(name = "requiredBean")
	public SpringService springService() {
		return new SpringService();
	}

}

Now run the main class to see the below output:

Spring service fully qualified class name: class com.roytuts.spring.conditional.on.bean.SpringService

Now if you change as @ConditionalOnBean(name = "RequiredBean") then you will see below error in the console because bean with name RequiredBean does not exist.

Bean method 'springService' in 'SpringConfig' not loaded because @ConditionalOnBean (names: RequiredBean; SearchStrategy: all) did not find any beans named RequiredBean

@ConditionalOnBean – by name

I had passed single bean name in the above example and now I will pass multiple names and check the results.

@Configuration
public class SpringConfig {

	@Bean
	@ConditionalOnBean(name = { "requiredBean", "anotherRequiredBean" })
	public SpringService springService() {
		return new SpringService();
	}

}

You will find same output in the console with new SpringService instance.

@ConditionalOnBean – by type

Next I will pass value by type in the @ConditionalOnBean annotation.

@Configuration
public class SpringConfig {

	@Bean

	@ConditionalOnBean(type = "com.roytuts.spring.conditional.on.bean.RequiredBean")
	public SpringService springService() {
		return new SpringService();
	}

}

You will get the same output as for the by name.

@ConditionalOnBean – by search

Strategy to decide if the application context hierarchy (parent contexts) should be considered. It the search strategy. The default search strategy is ALL. Others are ANCESTORS and CURRENT.

@Configuration
public class SpringConfig {

	@Bean
	@ConditionalOnBean(search = SearchStrategy.CURRENT, type = "com.roytuts.spring.conditional.on.bean.RequiredBean")
	public SpringService springService() {
		return new SpringService();
	}

}

You will get the same output as for the by name.

@ConditionalOnBean does not prevent @Configuration classes from being created.

Source Code

Download

Leave a Reply

Your email address will not be published. Required fields are marked *