New 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
//simple register of bean by its class
public final <T> void registerBean(Class<T> beanClass, BeanDefinitionCustomizer... customizers) {....}
//simple register of bean by its name and class
public final <T> void registerBean(@Nullable String beanName, Class<T> beanClass
, BeanDefinitionCustomizer... customizers){....}
//following two 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
package org.springframework.beans.factory.config;
....
@FunctionalInterface
public interface BeanDefinitionCustomizer {
//Customize the given bean definition.
void customize(BeanDefinition bd);
}
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 last 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, isntance: %s%n",
item, qty, System.identityHashCode(this));
if (logService != null) {
logService.log("Order placed");
}
}
private void init() {
System.out.printf("%s, init method called: %s%n", this.getClass().getName(),
System.identityHashCode(this));
}
private void destroy() {
System.out.printf("%s, destroy method called: %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: ", this.getClass().getName(),
System.identityHashCode(this));
}
}
}
Using new methods of BeanDefinitionCustomizer
Not using any customizer:
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: 1077921131 context refreshed placing order item: Laptop, qty: 2, isntance: 1077921131 ----------- placing order item: Desktop, qty: 2, isntance: 1077921131
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: 810800908 placing order item: Laptop, qty: 2, isntance: 810800908 ----------- instance of OrderService$OrderServiceImpl created: 56436313 placing order item: Desktop, qty: 3, isntance: 56436313
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: 203610909 placing order item: Laptop, qty: 2, isntance: 203610909
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: 762635420 LogService$LogServiceImpl, init method called: 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: 546392465 LogService$LogServiceImpl, init method called: instance of OrderService$OrderServiceImpl created: 1138452033 OrderService$OrderServiceImpl, init method called: 1138452033 context refreshed placing order item: Laptop, qty: 2, isntance: 1138452033 Order placed OrderService$OrderServiceImpl, destroy method called: 1138452033
Example ProjectDependencies and Technologies Used: - spring-context 5.1.2.RELEASE: Spring Context.
- JDK 1.8
- Maven 3.5.4
|