Spring 5 Functional Bean Registration

1. Overview

Spring 5 comes with support for functional bean registration in the application context.

Simply put, this can be done through overloaded versions of a new registerBean() method defined in the GenericApplicationContext class.

Let’s have a look at a few examples of this functionality in action.

2. Maven Dependencies

The quickest way to setup a Spring 5 project is to use Spring Boot by adding the spring-boot-starter-parent dependency to the pom.xml:

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

We also need the spring-boot-starter-web and spring-boot-starter-test for our example, to use a web application context in a JUnit test:

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

Of course, Spring Boot is not necessary in order to use the new functional way to register a bean. We could also just add the spring-core dependency directly:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>5.3.3</version>
</dependency>

3. Functional Bean Registration

The registerBean() API can receive two types of functional interfaces as parameters:

  • Supplier argument used to create the object
  • BeanDefinitionCustomizer vararg which can be used to provide one or more lambda expressions to customize the BeanDefinition; this interface has a single customize() method

First, let’s create a very simple class definition that we will use to create beans:

public class MyService {
    public int getRandomNumber() {
        return new Random().nextInt(10);
    }
}

Let’s also add a @SpringBootApplication class that we can use to run a JUnit test:

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

Next, we can set up our test class using the @SpringBootTest annotation to create a GenericWebApplicationContext instance:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Spring5Application.class)
public class BeanRegistrationIntegrationTest {
    @Autowired
    private GenericWebApplicationContext context;
   
    //...
}

We’re using the GenericWebApplicationContext type in our example, but any type of application context can be used in the same way to register a bean.

Let’s see how we can register a bean using a lambda expression for creating the instance:

context.registerBean(MyService.class, () -> new MyService());

Let’s verify that we can now retrieve the bean and use it:

MyService myService = (MyService) context.getBean("com.maixuanviet.functional.MyService"); 
 
assertTrue(myService.getRandomNumber() < 10);

We can see in this example that if the bean name isn’t explicitly defined, it will be determined from the lower-case name of the class. The same method above can also be used with an explicit bean name:

context.registerBean("mySecondService", MyService.class, () -> new MyService());

Next, let’s see how we can register a bean by adding a lambda expression to customize it:

context.registerBean("myCallbackService", MyService.class, 
  () -> new MyService(), bd -> bd.setAutowireCandidate(false));

This argument is a callback that we can use to set bean properties such as autowire-candidate flag or primary flag.

4. Conclusion

In this quick tutorial, we’ve seen how we can use the functional way of registering a bean.

The source code for the example can be found over on GitHub.

Related posts:

Giới thiệu java.io.tmpdir
Guide to BufferedReader
Mệnh đề Switch-case trong java
Java Program to Check if a Matrix is Invertible
Java Program to Generate a Random UnDirected Graph for a Given Number of Edges
Servlet 3 Async Support with Spring MVC and Spring Security
Primitive Type Streams in Java 8
Using a Spring Cloud App Starter
Java Program to Implement Doubly Linked List
Java Program to implement Dynamic Array
Autoboxing và Unboxing trong Java
Java Program to Construct an Expression Tree for an Prefix Expression
Guide to PriorityBlockingQueue in Java
REST Web service: Upload và Download file với Jersey 2.x
An Introduction to Java.util.Hashtable Class
Java Program to Implement Solovay Strassen Primality Test Algorithm
Java Program to Find k Numbers Closest to Median of S, Where S is a Set of n Numbers
Từ khóa throw và throws trong Java
Java CyclicBarrier vs CountDownLatch
Giới thiệu về Stream API trong Java 8
A Guide To UDP In Java
Apache Commons Collections MapUtils
REST Web service: Tạo ứng dụng Java RESTful Client với Jersey Client 2.x
The SpringJUnitConfig and SpringJUnitWebConfig Annotations in Spring 5
Wiring in Spring: @Autowired, @Resource and @Inject
So sánh HashSet, LinkedHashSet và TreeSet trong Java
SOAP Web service: Upload và Download file sử dụng MTOM trong JAX-WS
Java Program to Perform Partition of an Integer in All Possible Ways
The Guide to RestTemplate
Java Web Services – Jersey JAX-RS – REST và sử dụng REST API testing tools với Postman
Java Program to Represent Linear Equations in Matrix Form
Java Program to Implement Efficient O(log n) Fibonacci generator