What Default order of beans creating in Spring Boot if we don't use #DependsOn and #Order?
I searched for documentation and found only "How to control the order of creating"
From this Spring doc (scroll down a bit):
...Your target beans can implement the
org.springframework.core.Ordered interface or use the #Order or
standard #Priority annotation if you want items in the array or list
to be sorted in a specific order. Otherwise, their order follows the
registration order of the corresponding target bean definitions in the
container.
You can declare the #Order annotation at the target class level and on
#Bean methods, potentially for individual bean definitions (in case of
multiple definitions that use the same bean class). #Order values may
influence priorities at injection points, but be aware that they do
not influence singleton startup order, which is an orthogonal concern
determined by dependency relationships and #DependsOn declarations.
Related
I am trying to invoke an operation of a set of beans by retrieving them from appContext.getBeanDefinitionNames().The order of invoking the operation matters to me as one bean's operation is dependent on other.
I have tried the following to set this order.
1.PriorityOrdered interface
2.#DependsOn annotation
3.BeansPostProcessor interface
But none of them seem to influence the order in the list. By default it is returning the beans in the order in which they are encountered in classpath.
Two questions.
1.What does it mean when the above approaches set the order of initialization to the bean?
2.Can the order of retrieval of bean names using appContext.getBeanDefinitionNames() be influenced in any way?
I didn't understand from your question what is really your problem. Do you want to alter the order of initializing beans or to get the names of beans in the order they have been defined in your configurations?
1.What does it mean when the above approaches set the order of initialization to the bean?
ApplicationContext is responsible for instantiating, configuring and wiring your application's beans. ApplicationContext in an early step of it's life cycle reads your configurations (XML, Annotations, Java code configurations, etc) and instantiates those beans. When we are talking about the order of initializing beans, we mean which bean will be instantiated by the ApplicationContext sooner and which will be instantiated later. For example if you have two classes A and B in which B depends on A like below:
class A {
}
class B {
private A a;
public B(A a) {
this.a = a;
}
}
As you can see in order to instantiate B we need an instance of A.
DependsOn
Beans on which the current bean depends. Any beans specified are guaranteed to be created by the container before this bean. (DependsOn Documentation)
BeanPostProcessor
A BeanPostProcessor allows you to modify a been after it is instantiated by the container. I don't think you can achieve what you want with a bean post processor. Docs
PriorityOrdered
PriorityOrdered is an extension of Ordered interface. From the documentation:
Ordered is an interface that can be implemented by objects that should
be orderable, for example in a Collection. The actual order can be
interpreted as prioritization, with the first object (with the lowest
order value) having the highest priority.
Note that there is also a priority marker for this interface:
PriorityOrdered. Order values expressed by PriorityOrdered objects
always apply before same order values expressed by plain Ordered
objects.
From the documentation of PriorityOrdered
Extension of the Ordered interface, expressing a priority ordering:
order values expressed by PriorityOrdered objects always apply before
same order values expressed by plain Ordered objects. This is
primarily a special-purpose interface, used for objects where it is
particularly important to recognize prioritized objects first, without
even obtaining the remaining objects. A typical example: prioritized
post-processors in a Spring ApplicationContext.
Also I don't think you can achieve what you want from this interface too.
2.Can the order of retrieval of bean names using appContext.getBeanDefinitionNames() be influenced in any way?
The getBeanDefinitionNames() method only returns an array of strings containing the names of all the beans defined in the current factory (Docs).
I'm totally new to CDI.
I'm used at configuring beans in XML (Spring). In CDI, should I configure them in classes directly? I have tens of beans with the same implementation but different configuration.
CDI uses a mixture of annotations and xml configuration to configure which beans are active in the deployment. It's a big topic but I'll attempt to summarise:
On your bean implementations you can use the following standard annotations:
#Default
#Alterative
#Vetoed
#Specializes
#Default is assumed unless no other annotations are present
#Alternative beans are not active unless specified so in your META-INF/beans.xml
#Vetoed beans are never considered active
#Specializes beans will always take precedence over their superclasses.
In addition to those you can create your own qualifiers to more accurately select which bean you want for what purpose.
You would create a qualifier as an annotation like this:
#Qualifier
#Retention(RUNTIME)
#Target({ TYPE, FIELD, PARAMETER, METHOD })
public #interface MyQualifier {
}
Note the #Qualifier and #Retention(RUNTIME) annotations.
You can also add parameters to your customer qualifier.
I would recommend giving the Weld documentation a read, it's comprehensive and quite well written:
Weld manual
Yes, configuration happens within the code. There have been several attempts at doing XML based configuration, look for Seam Config.
For your tens of beans, you would typically use producer methods to create the individual implementations with their own configuration. CDI uses qualifiers, rather than bean ids to identify beans.
I'm wondering if I add a #Value annotation on a property, the class who contains this property cannot be used by another one with a different value, Example :
MyClassUtil.java had
#Value("${some.value}")
private int _myProperty;
And of course there is one module.properties who contain :
some.value=10
Another class ClassA.java wants to use this class with value 10. Ok, no problem.
But another class ClassB.java wants to use this class but with another value : 20. I cannot do this if I'm not mistaken.
Because before #Value era, I could declare two beans in the moduleContext.xml without any problem.
So, is #Value pushes you to do some strong coupling ?
You are right that the annotation configuration can not be instance specific. It is important to understand the concept of bean definitions in bean factory.
Manual bean definition:
Single <bean> element in your XML config leads to a single bean definition. Multiple <bean> mean multiple definitions (regardless of a bean type).
Single #Bean method within #Configuration class leads to a single bean definition. Multiple #Bean methods mean multiple definitions (regardless of a bean type).
However when using component scan, classes annotated with #Component-like annotations are auto-registered as a single bean definition. There is no way you can register bean multiple times via component scan.
Similarly, annotation configurations (#Value, #Autowired, etc.) are type-wide. Your bean instances are always augmented and processed with the same effect (e.g. injecting the same value). There is no way you can alter annotation processing behaviour from instance to instance.
Is this tight coupling? It is not in its general understanding - bean factory (Spring) is still free to inject whatever it thinks is suitable. However it is more of a service lookup pattern. This simplifies your life when working with domain specific singletons. And most beans in an application context tend to be singletons, many of them domain specific (controllers, services, DAOs). Framework singletons (non-project specific reusable classes) should never use annotation based configuration - in this scope, it is an unwanted tight coupling.
If you need different bean instances, you should not use annotation configuration and define your beans manually.
Is there any way to inject bean dependencies make configurable except from factory pattern?
I have 3 class implement same interface and have 3 bean definition. I want to change that beans using in other class? For excample is it possile to read bean name form conf file and use it as varible?
Yes, you can go with #Qualifier annotation. As you have 3 classes which implement same interface, name those classes with different names and use #Qualifier annotation.
Spring documentation says : autowiring by type may lead to multiple candidates, it is often necessary to have more control over the selection process. One way to accomplish this is with Spring's #Qualifier annotation.
Our app has a requirement to support multi-tenancy. Each of the boarded customer might potentially override 1 or more beans or some properties of a bean defined at the core platform level (common code/definitions). I am wondering what is the best way to handle this.
Spring allows you to redefine the same bean name multiple times, and takes the last bean definition processed for a given name to be the one that wins. So for example, your could have an XML file defining your core beans, and import that in a client-specific XML file, which also redefines some of those beans. It's a bit fragile, though, since there's no mechanism to specifically say "this bean definition is an override".
I've found that the cleanest way to handle this is using the new #Bean-syntax introduced in Spring 3. Rather than defining beans as XML, you define them in Java. So your core beans would be defined in one #Bean-annotated class, and your client configs would subclass that, and override the appropriate beans. This allows you to use standard java #Override annotations, explicitly indicating that a given bean definition is being overridden.