Introduction

We will create examples on Spring @ConditionalOnBean. Anywhere we define a Spring bean, we 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, we 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

Eclipse Neon, Java 1.8, Gradle 5.4.2, Spring Boot 2.1.7

Creating Project

Create a gradle based project in Eclipse with the project name as spring-conditional-on-bean.

Updating Build Script

The default generated build.gradle script does not include required dependencies, so we will update the build script as follows to include the spring boot dependencies.

buildscript {
	ext {
		springBootVersion = '2.1.7.RELEASE'
	}
    repositories {
    	mavenLocal()
    	mavenCentral()
    }
    dependencies {
    	classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}
apply plugin: 'java'
apply plugin: 'org.springframework.boot'
sourceCompatibility = 1.8
targetCompatibility = 1.8
repositories {
	mavenLocal()
    mavenCentral()
}
dependencies {
	implementation("org.springframework.boot:spring-boot-starter-web:${springBootVersion}")
}

Creating Service Class

We 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

We will create various ways of using @ConditionalOnBean annotation.

Creating Simple Beans

We 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

We 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 {
}

Creating Examples

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

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

We will also create a main class to run our application. The source of the main class is given below. We will not modify our main class but we 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 we will see @ConditionalOnBean by value in Spring Config class.

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

We will now use by passing the bean name for the value name. Here we are passing single bean names but you can also pass multiple bean names and we will see on this after this example.

As we have annotated class RequiredBean with @Component and by default bean name is resolved as class name with initial letter in lower case, so we 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

We had passed single bean name in the above example and now we 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 we 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.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

You can download source code.

Thanks for reading.

Tags:

Leave a Reply

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