Spring 5 methods in GenericApplicationContext
The existing class GenericApplicationContext is an implementation of ConfigurableApplicationContext interface. This class also implements BeanDefinitionRegistry interface. Typical usage of this class is to register a variety of bean definitions via the BeanDefinitionRegistry interface. In addition to the existing method registerBeanDefinition(beanName, beanDefinition), Spring 5.0 added following new convenient methods for registering beans:
package org.springframework.context.support;
......
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
//existing implementation of BeanDefinitionRegistry#registerBeanDefinition method
@Override
public void registerBeanDefinition(String beanName,
BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {....}
//spring 5.0 new methods
//registering a bean by its class
public final <T> void registerBean(Class<T> beanClass,
BeanDefinitionCustomizer... customizers) {....}
//registering a bean by its name and class
public final <T> void registerBean(@Nullable String beanName,
Class<T> beanClass,
BeanDefinitionCustomizer... customizers){....}
//following two new methods uses Java 8 Supplier which return the bean instance themselves, hence no reflection
//involved in bean creation
public final <T> void registerBean(Class<T> beanClass,
Supplier<T> supplier,
BeanDefinitionCustomizer... customizers) {....}
public <T> void registerBean(@Nullable String beanName,
Class<T> beanClass,
@Nullable Supplier<T> supplier,
BeanDefinitionCustomizer... customizers) {....}
}
Note that all new methods' last parameter is of new Spring 5.0 interface BeanDefinitionCustomizer.
GenericApplicationContext must call AbstractApplicationContext.refresh() to initialize the registered beans.
Spring 5.0 new interface BeanDefinitionCustomizer
Definition of BeanDefinitionCustomizerVersion: 7.0.3 package org.springframework.beans.factory.config;
@FunctionalInterface
public interface BeanDefinitionCustomizer {
void customize(BeanDefinition bd); 1
}
This interface can be used as a callback for customizing a given bean definition. It is designed for use with Java 8 lambda expressions or method references. Check out previous tutorial on how to use BeanDefinition
Examples
Beans
public interface OrderService {
void placeOrder(String item,
int qty);
public static class OrderServiceImpl implements OrderService {
private LogService logService;
public OrderServiceImpl() {
System.out.printf("instance of %s created: %s%n",
this.getClass().getName(),
System.identityHashCode(this));
}
public OrderServiceImpl(LogService logService) {
this();
this.logService = logService;
}
public void setLogService(LogService logService) {
this.logService = logService;
}
@Override
public void placeOrder(String item,
int qty) {
System.out.printf("placing order item: %s, qty: %s, instance: %s%n",
item, qty, System.identityHashCode(this));
if (logService != null) {
logService.log("Order placed");
}
}
private void init() {
System.out.printf("%s, init method called, instance: %s%n",
this.getClass().getName(),
System.identityHashCode(this));
}
private void destroy() {
System.out.printf("%s, destroy method called, instance: %s%n",
this.getClass().getName(),
System.identityHashCode(this));
}
}
}
public interface LogService {
void log(String msg);
class LogServiceImpl implements LogService {
public LogServiceImpl() {
System.out.printf("instance of %s created: %s%n",
this.getClass().getName(),
System.identityHashCode(this));
}
@Override
public void log(String msg) {
System.out.println(msg);
}
private void init() {
System.out.printf("%s, init method called, instance: %s%n",
this.getClass().getName(),
System.identityHashCode(this));
}
}
}
Using new methods of BeanDefinitionCustomizer
Not using any customizer yet:
import org.springframework.context.support.GenericApplicationContext;
public class RegisterBeanExample1 {
//using registerBean(beanClass, customizers)
public static void main(String[] args) {
GenericApplicationContext gac = new GenericApplicationContext();
gac.registerBean(OrderService.OrderServiceImpl.class);//not using customizer
gac.refresh();
System.out.println("context refreshed");
OrderService os = gac.getBean(OrderService.class);
os.placeOrder("Laptop", 2);
System.out.println("-----------");
//retrieving the bean one more time
os = gac.getBean(OrderService.class);
os.placeOrder("Desktop", 2);
gac.close();
}
}Outputinstance of OrderService$OrderServiceImpl created: 6688698 context refreshed placing order item: Laptop, qty: 2, instance: 6688698 ----------- placing order item: Desktop, qty: 2, instance: 6688698
Creating customizers
We have created a util class for BeanDefinitionCustomizers, so its methods can be used as Java 8 method references:
public class Customizers {
public static void prototypeScoped(BeanDefinition bd) {
bd.setScope(ConfigurableBeanFactory.SCOPE_PROTOTYPE);
}
public static void lazy(BeanDefinition bd) {
bd.setScope(ConfigurableBeanFactory.SCOPE_PROTOTYPE);
}
public static void defaultInitMethod(BeanDefinition bd) {
bd.setInitMethodName("init");
}
public static void defaultDestroyMethod(BeanDefinition bd) {
bd.setDestroyMethodName("destroy");
}
}
Registering bean as prototype scoped bean
import org.springframework.context.support.GenericApplicationContext;
public class RegisterBeanExample2 {
//using registerBean(beanClass, customizers)
public static void main(String[] args) {
GenericApplicationContext gac = new GenericApplicationContext();
gac.registerBean(OrderService.OrderServiceImpl.class,
Customizers::prototypeScoped);
gac.refresh();
System.out.println("context refreshed");
OrderService os = gac.getBean(OrderService.class);
os.placeOrder("Laptop", 2);
System.out.println("-----------");
//retrieving the bean one more time
os = gac.getBean(OrderService.class);
os.placeOrder("Desktop", 3);
gac.close();
}
}Outputcontext refreshed instance of OrderService$OrderServiceImpl created: 1579577798 placing order item: Laptop, qty: 2, instance: 1579577798 ----------- instance of OrderService$OrderServiceImpl created: 1628944913 placing order item: Desktop, qty: 3, instance: 1628944913
Registering bean by name
import org.springframework.context.support.GenericApplicationContext;
public class RegisterBeanExample3 {
//using registerBean(beanName, beanClass, customizers)
public static void main(String[] args) {
GenericApplicationContext gac = new GenericApplicationContext();
gac.registerBean("orderBean", OrderService.OrderServiceImpl.class,
Customizers::lazy);
gac.refresh();
System.out.println("context refreshed");
OrderService os = (OrderService) gac.getBean("orderBean");
os.placeOrder("Laptop", 2);
gac.close();
}
}Outputcontext refreshed instance of OrderService$OrderServiceImpl created: 699448661 placing order item: Laptop, qty: 2, instance: 699448661
Using multiple BeanDefinitionCustomizers
import org.springframework.context.support.GenericApplicationContext;
public class RegisterBeanExample4 {
//using registerBean(beanClass, beanSupplier, customizers)
public static void main(String[] args) {
GenericApplicationContext gac = new GenericApplicationContext();
gac.registerBean(LogService.class,
LogService.LogServiceImpl::new,
Customizers::lazy,
Customizers::defaultInitMethod);
gac.refresh();
System.out.println("context refreshed");
LogService ls = gac.getBean(LogService.class);
ls.log("msg from main method");
gac.close();
}
}
Outputcontext refreshed instance of LogService$LogServiceImpl created: 157090513 LogService$LogServiceImpl, init method called, instance: 157090513 msg from main method
Injecting other bean via constructor
import org.springframework.context.support.GenericApplicationContext;
public class RegisterBeanExample5 {
//injecting other bean via constructor
public static void main(String[] args) {
GenericApplicationContext gac = new GenericApplicationContext();
gac.registerBean(LogService.class, LogService.LogServiceImpl::new,
Customizers::lazy,
Customizers::defaultInitMethod);
gac.registerBean(OrderService.OrderServiceImpl.class,
Customizers::defaultInitMethod,
Customizers::defaultDestroyMethod);
gac.refresh();
System.out.println("context refreshed");
OrderService os = gac.getBean(OrderService.class);
os.placeOrder("Laptop", 2);
gac.close();
}
}
Outputinstance of LogService$LogServiceImpl created: 2099757575 LogService$LogServiceImpl, init method called, instance: 2099757575 instance of OrderService$OrderServiceImpl created: 1966723992 OrderService$OrderServiceImpl, init method called, instance: 1966723992 context refreshed placing order item: Laptop, qty: 2, instance: 1966723992 Order placed OrderService$OrderServiceImpl, destroy method called, instance: 1966723992
Example ProjectDependencies and Technologies Used: - spring-context 7.0.3 (Spring Context)
Version Compatibility: 5.0.0.RELEASE - 7.0.3 Version compatibilities of spring-context with this example: Versions in green have been tested.
- JDK 25
- Maven 3.9.11
|