Spring DI of Constructor parameter with Collection in auto-configure - spring

I m wondering about some Constructor injection in spring boot when creating beans .
For example , in spring boot auto-configure , The JacksonAutoConfiguration file
#Bean
#Scope("prototype")
#ConditionalOnMissingBean
Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder(ApplicationContext applicationContext,
List<Jackson2ObjectMapperBuilderCustomizer> customizers) {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.applicationContext(applicationContext);
customize(builder, customizers);
return builder;
}
where is the Where the List <Jackson2ObjectMapperBuilderCustomizer comes from?
I dont see any bean declaration about this object. It it not a inter-reference between beans. I m very confused about it.

Arguments in a bean definition are not always "other beans" defined elsewhere, but can be simply "free" arguments. In that case the bean definition is just a method: you call it with the required arguments, and it will return the result.
Because this "free" arguments are not known in advance, you must tell to Spring that:
it can't instantiate the bean as a default "singleton", using the scope "prototype"
it's about "you" to call the method with the given arguments, usually with the BeanFactory.getBean(Class cl, Object... arguments)
In the code you shown, spring-boot will have somewhere a call like this
beanFactory.getBean(Jackson2ObjectMapperBuilder.class, applicationContext, cusomizerList)
to be able to istantiate a Jackson2ObjectMapperBuilder bean that will be aware of:
a specific applicationContext (there could be more than one in a Spring application)
and some 'customizers' to probably let configure in some way the Jackson mapper.
In this way you can obtain a bean that can be built with arguments that are available only at run-time. This is useful in this case at "configuration" run-time, but is a very powerful way to build "smart beans" in your own application.
Note on 'The evil parts of Spring'
The default behavior of Spring is to build 'singleton' aka #Service beans. A singleton bean in a multi-thread application needs to be without fields to be thread-safe.
This brings to a totally 'procedural' design often defeating all advantages of a proper Object-Oriented approach (that needs fields to manage an internal state and offer of course an higher abstraction level).

Related

Factory design pattern and Spring

I am wondering what is the current best practice as to the use of factory pattern within the context of Spring framework in using dependency injection. My wonder arises about whether the factory pattern is still relevant nowadays in light of the use of Spring dependency injection. I did some searching and see some past discussion (Dependency Injection vs Factory Pattern) but seem there is different view.
I see in some real life project in using a Map to hold all the beans and rely on autowiring to create those beans. When the bean is needed, it get it via the map using the key.
public abstract class Service {
//some methods
}
#Component
public class serviceA extends Service {
//implementation
}
#Component
public class serviceB extends Service {
//implementation
}
Map<String, Service> services;
But I see there is some difference among the two approaches.
Using the above method, all beans are created on application start up and the creation of object is handled by the framework. It also implies there is only one bean for each type.
While for factory pattern, the factory class creates the object on request. And it can create a new object for each request.
I think a deeper question may be, when Spring framework is used in a project, should it be strived to not create any object inside a class, which means the factory pattern ( or any creational design patterns?) should not be used, as Spring is supposed to be the central handler of the objects dependency ?
The answer to this question can be really deep and broad, I'll try to provide some points that hopefully will help.
First off, spring stores its beans (singletons) in the ApplicationContext. Essentially this is the map you're talking about. In a nutshell, it allows getting the bean by name, type, etc.
ApplicationContext, while being a really important concept, is not the whole Spring, in fact Spring framework allows much more flexibility:
You say, using a map implies that all the beans will be created at the beginning of the application and there is one instance of the bean.
Spring has a concept of Lazy beans, basically supporting a concept of beans being actually created only when they're required for the first time, so Spring supports the "delayed" beans initialization
Spring also allows more than one instance of a bean per type. So this map is more "advanced". For example you can create more than one implementation of the interface and use declare both as beans. As long as you provide enough information about what bean should be injected to the class that might use them (for example with a help of qualifiers suppored in spring), you're good to go. In addition, there are features in spring IoC container that allow injecting all registered implementations of an interface into a list:
interface Foo {}
#Component
class FooImpl1 implements Foo {}
#Component
class FooImpl2 implements Foo {}
class Client {
#Autowired
List<Foo> allFoos;
}
Now you say:
While for factory pattern, the factory class creates the object on request. And it can create a new object for each request.
Actually Spring can create objects per request. Not all beans have to be singletons, in general spring has a concept of scopes for this purposes.
For example, scope prototype means that Spring will create a bean upon each usage. In particular one interesting usage that spring supports in variety of ways is Injecting prototype bean into singleton. Some solutions use exactly like a factory (read about annotation #Lookup others rely on auto-generated proxy in runtime (like javax.inject.Provider). Prototype scope beans are not held in the application context, so here again spring goes beyond a simple map abstraction.
Last feature that you haven't mentioned is that sometimes even for singletons the initialization can be a little bit more complicated then calling a constructor with Parameters. Spring can address that by using Java Configurations:
#Configuration
public class MyConfig {
public SomeComplicatedObject foo(#Value("...") config, Bar bar) {
SomeComplicatedObject obj = new SomeComplicatedObject() // lets pretend this object is from some thirdparty, it only has no-op constructor, and you can't place spring annotations on it (basically you can't change it):
obj.setConfig(config);
obj.setBar(bar);
return obj;
}
}
The method foo here initializes the object SomeComplicatedObject and returns it. This can be used instead of factories to integrate "legacy" code (well, java configurations go way beyond this, but its out of scope for this question).
So bottom line, you Spring as an IoC container can provide many different ways to deal with object creation, in particular it can do everything that factory design pattern offers.
Now, I would like to also refer to your last sentense:
I think a deeper question may be, when Spring framework is used in a project, should it be strived to not create any object inside a class, which means the factory pattern ( or any creational design patterns?) should not be used, as Spring is supposed to be the central handler of the objects dependency ?
Indeed you don't have to use Factory Pattern when using Spring, since (as I hopefully have convinced you) provides everything that factory can do and more.
Also I agree that spring is supposed to be the central handler of the objects dependency (unless there are also parts of the application which are written in a different manner so you have to support both :) )
I don't think we should avoid using "new" altogether, not everything should/can be a bean, but I do see (from my subjective experience, so this is arguable) that you use it much less leaving the creation of most of the objects to Spring.
Should we avoid a usage of any creation design pattern? I don't think so, sometimes you can opt for implementing "builder" design pattern for example, its also a creational pattern but spring doesn't provide a similar abstraction.
I think if your project uses Spring framework you should use it. Although it depends on your project design e.g. You may use creational patterns along side with Spring IoC. e.g when you have abstraction layers not framework dependant (agnostic code)
interface ServiceFactory {
Service create(String type);
}
#Component
class SpringServiceFactory implements ServiceFactory {
#Autowired private ApplicationContext context;
Service create(String type) {
return context.getBean(type)
}
}
I use Factory pattern as well when I refactor legacy not unit testable code which also uses Spring Framework in order to implement unit tests.
// legacy service impossible to mock
class LegacyApiClient implements Closeable {...}
#Component
class LegacyApiClientFactory {
LegacyApiClient create(String endpoint) {
return new LegacyApiClient(endpoint);
}
}
#Component
class OtherService {
private final String endpoint
private final LegacyApiClientFactory factory;
OtherService(#Value("${post.endpoint}") String endpoint,
LegacyApiClientFactory factory) {...}
void doCall {
try (LegacyApiClient client = factory.create(endpoint)) {
client.postSomething();
}
}
}
....
// a random unit test
LegacyApiClient client = mock(LegacyApiClient.class)
LegacyApiClientFactory factory = mock(LegacyApiClientFactory.class)
OtherService service = new OtherService("http://scxsc", factory);
when(factory.create(any())).thenReturn(client)
service.doCall()
....

Spring - register Beans before everything else

I need to register a series of BeanDefinition(s) before every other Bean gets created. That's because those registered Bean(s) are needed for autowiring and ApplicationContext#getBean calls.
I cannot use #DependsOn, obviously.
Example:
final var beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(...);
beanDefinition.setLazyInit(true);
beanDefinition.setAbstract(false);
beanDefinition.setAutowireCandidate(true);
beanDefinition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
beanDefinition.setScope(BeanDefinition.SCOPE_PROTOTYPE);
registry.registerBeanDefinition("...", beanDefinition);
Which point/interface/lister can I use to obtain this? Keep in mind I need an instance of BeanDefinitionRegistry.
Adding explanation as required.
Those definitions are created from a list of Classes gathered by scanning the classpath. Those classes are not Spring Bean(s) natively, so I need to integrate them into my ApplicationContext. Those classes, however, accepts constructor arguments which are Spring Beans.
That's why I'm setting
beanDefinition.setAutowireCandidate(true);
beanDefinition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
Those new registered Beans are there used by other Bean(s) (native Beans).
You are trying to make the solution too complex. If your only goal is to have non #Component annotated classes be detected by component scanning and have them used as Spring Beans simply define a custom includeFilter for the #COmponentScan.
You can use a filter of type ASPECTJ or REGEX to match a package or type.
#ComponentScan(includeFilter = #Filter(type=REGEX, expression="com.foo.bar.*))
Something like that will automatically detect your beans (assuming they are in a packaged being scanned) and create spring beans out of them. If they have a single constructor that will automatically be used to create an instance.
Register a new BeanFactoryPostProcessor or BeanDefinitionRegistryPostProcessor bean in your context. This bean will get invoked after bean definitions are scanned but before actual beans are constructed:
Extension to the standard BeanFactoryPostProcessor SPI, allowing for the registration of further bean definitions before regular BeanFactoryPostProcessor detection kicks in. In particular, BeanDefinitionRegistryPostProcessor may register further bean definitions which in turn define BeanFactoryPostProcessor instances.

Spring how to enforce use of bean factory, for prototype beans with runtime arguments

In my spring-boot application i have "normal" singleton beans that "autowire" the stuff they need via a private constructor. So it is not possible to call "new" anywhere in the code.
But i also have "prototype" beans that need runtime arguments to be created. To create such beans i could use this approach (lazy instantiated protype beans): Spring bean with runtime constructor arguments
The problem is that the constructor is used and hence must be "visible". Is there any way in Spring to create such prototype beans with a private constructor? I want to enforce the usage of BeanFactory to create them.
You can try to build your prototype beans with an implementation of
factoryBean,public interface FactoryBean<T> {
T getObject() throws Exception;
Class<T> getObjectType();
boolean isSingleton();
}
So you can encapsulate more complexe logic inside,
A full exemple here

Difference between beanFactoryPostProcessor and postProcessBeforeInitialization [duplicate]

I was trying to understand the difference between BeanFactoryPostProcessor and BeanPostProcessor.
I understood that BeanFactoryPostProcessor operates on bean definition i.e. before the bean instance is getting created it gets executed and BeanPostProcessor gets executed after bean is instantiated and lifecycle events are called.
Does this mean BeanFactoryPostProcessor is not a part of spring lifecycle events as it's called before instantiation while BeanPostProcessor is the part of Spring lifecycle events? Kindly verify if my understanding is right.
BeanFactoryPostProcessor is an interface and beans that implement it are actually beans that undergo the Spring lifecycle (Example below) but these beans don't take part of the other declared beans' lifecycle.
public class CustomBeanFactory implements BeanFactoryPostProcessor {
#Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
for (String beanName : beanFactory.getBeanDefinitionNames()) {
BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
// Manipulate the beanDefiniton or whatever you need to do
}
}
}
The differences about BeanFactoryPostProcessor and BeanPostProcessor:
A bean implementing BeanFactoryPostProcessor is called when all bean definitions will have been loaded, but no beans will have been instantiated yet. This allows for overriding or adding properties even to eager-initializing beans. This will let you have access to all the beans that you have defined in XML or that are annotated (scanned via component-scan).
A bean implementing BeanPostProcessor operate on bean (or object) instances which means that when the Spring IoC container instantiates a bean instance then BeanPostProcessor interfaces do their work.
BeanFactoryPostProcessor implementations are "called" during startup of the Spring context after all bean definitions will have been loaded while BeanPostProcessor are "called" when the Spring IoC container instantiates a bean (i.e. during the startup for all the singleton and on demand for the proptotypes one)
Here is a flow diagram that might help to understand the spring bean initialisation life cycle.
As we can see, the implementation of theBeanFactoryPostProcessor is executed before any spring bean instantiation, contrary to the BeanPostprocessor, where the implemented method will be executed only when the bean is instantiated.
The source image is from the Spring 5 Design Patterns Book.
I pick the explanation from the book:
After loading the bean definitions from all styles of configurations,
BeanFactoryPostProcessor comes into the picture to modify the
definition of some beans, and then the container instantiates the
beans. Finally, BeanPostProcessor works on the beans, and it can
modify and change the bean object. This is the initialization phase.
Bean Factory Post Procesor (BFPP):
Used when we want to override XML / annotations, because Spring reads XML / annotations to create the beans. If you want to provide a different configuration to Spring during creation (at run time), then you need to use BFPP. Creating the internal dependency graph is a one time process.
Bean Post Processor (BPP):
The above step happened only once. It's like creating the "menu" of beans. After creating the bean, if you want to change the bean properties, you can't make any changes to the XML / annotations. Instead, you can use the BPP for bean configuration change after creation. The BPP has 2 execution areas, one before #postconstruct and one after #postconstruct.
Real Time Example:
You want to place an online food order from Zomato. While ordering online, you give a list of food (XML/annotations) to the restaurant. But, just before the restaurant starts making the food, you call them and ask them to change the dish (BFPP). Now the food is ready to be delivered and you've received it (Bean is created). But you want to make some modifications (like salt or chilly powder), and you can do this before tasting the food (because you know restaurants never put enough salt), or even after tasting the food (this is before and after #postconstruct). Once the taste is good, then the food is ready (the bean is ready to use).
The BeanFactoryPostProcessor executes before bean Object instantiation (ie at the time Applicationcontext container is initialized)
BeanPostprocessor is executed after the bean object is created, as it can be executed before init() and after init().

Spring: difference between Lookup method injection, Provider<T> , ObjectFactory and factoryBean

What are the differences between Lookup method injection, Provider<T>, ObjectFactory and factoryBean. If I want a new instance of a prototype (many times) into a singleton, which of them is the best solution?
And if I want a new instance (many times) of a prototype bean into a prototype?
please check my question too: How to instantiate spring managed beans at runtime?
As far as I understand the factoryBean is just a way to create bean with some complex instantiation logic. It is hard to define such logic in xml. It is well explained in spring documentation: http://springindepth.com/book/in-depth-ioc-factory-bean.html
Other three looks similar for me. But If you look at one spring issue https://jira.spring.io/browse/SPR-5192 you will find that javax.inject.Provider interface came from JSR-330 and I guess it was implemented in spring later than lookup method injection and looks like it is better solution. (The same thing is implemented in Google Guice DI)
Also with Object factory you have to write coupled with spring code(ObjectFactory requires spring import):
#Autowired
private ObjectFactory<PrototypeBean> beanFactory;
//...
beanFactory.getObject()
Upd
Lookup, beanFactory and Provider doesn't support passing any parameters, i.e. you have Provider#get() but there is no Provider#get(Object... args)

Resources