Spring @ConditionalOnBean Example

Introduction

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 at least 1.8, Maven 3.6.3, Spring Boot 2.1.7 – 2.4.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>12</maven.compiler.source>
		<maven.compiler.target>12</maven.compiler.target>
	</properties>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.4.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.

package com.roytuts.spring.conditional.on.bean;

public class SpringService {

}

Examples on @ConditionalOnBean

I will create various ways of using @ConditionalOnBean annotation.

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.

package com.roytuts.spring.conditional.on.bean;

import org.springframework.stereotype.Component;

@Component
public class RequiredBean {

}

Bean – AnotherRequiredBean

package com.roytuts.spring.conditional.on.bean;

import org.springframework.stereotype.Component;

@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.

package com.roytuts.spring.conditional.on.bean;

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 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.

package com.roytuts.spring.conditional.on.bean;

import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.SearchStrategy;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@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.

package com.roytuts.spring.conditional.on.bean;

import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@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.

package com.roytuts.spring.conditional.on.bean;

import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@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.

package com.roytuts.spring.conditional.on.bean;

import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@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.

package com.roytuts.spring.conditional.on.bean;

import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.SearchStrategy;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@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 *