Qualifier on Bean method - spring

Id, like to ask that what exactly a Qualifier annotation is doing on a Bean method? I thought it is the same as specifying a name inside the Bean annotation but a use-case proves otherwise:
The configuration:
#Bean
#Qualifier("myGroup")
public MyObject myObject1() {
return new MyObject("myObject1");
}
#Bean
#Qualifier("myGroup")
public MyObject myObject2() {
return new MyObject("myObject2");
}
#Bean
public MyObject myObject3() {
return new MyObject("myObject3");
}
The injection:
#Autowired
#Qualifier("myGroup")
private List<MyObject> myObjects;
The list myObjects will contain only myObject1 and myObject2, the ones that have the qualifier.
The bean names will be named by the method.
So my question would be, why, and how is this working?

This works because you're autowiring a list of MyObject. Autowiring multiple beans of the same class into a list containing that class is not an issue. I mean, it's different instances, yes but if you're autowiring a list of them then you should know why you're doing that.
If you do this then it won't work
#Autowired
#Qualifier("myGroup")
private MyObject myObjects;
because then myObject1 and myObject2 would both be qualified as autowiring candidate, which will throw Spring off. And since you put #Qualifier when autowiring, it only autowires beans that fit the name that's specified in the #Qualifier

Related

How to use Spring Prototype Scope and custom bean name?

I have 3 classes, lets say, ClassA, ClassB, ClassC that are going to collaborate over an use case, so let say my use case defines over an 'id' and 'source' fields an unique key, so for every unique combination of 'id', 'source' there will be instances InstanceA_id1_source1, InstanceB_id1_source1, InstanceC_id1_source1, ....(n)...
I am trying to inject a Bean to 'InstanceA_id1_source1, InstanceB_id1_source1, InstanceC_id1_source1' that will only exist for combination of 'id1' and 'source1'...
So my idea was to create with a bean with Prototype Scope for 'id1' and 'source1' and inject it to 'InstanceA_id1_source1, InstanceB_id1_source1, InstanceC_id1_source1' with a special name...
I managed to create the Bean in protoype mode..
#Component
class Config {
#Bean
#Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public ReceptionFacade someFacade(String id, String source) {
return new SomeFacade(id, source);
}
}
And I can get Instance at the class at 'InstanceA_id1_source1, InstanceB_id1_source1, InstanceC_id1_source1'....
#Autowired
BeanFactory beanFactory;
SomeFacade someFacade =
beanFactory.getBean(SomeFacade.class, id, source);
this works and I get for every call a different instance of the SomeFacade as expected from Prototype scope but what I wanted was to register this bean as 'someFacade_id1_source1' to Spring Context so I can re-inject it again with the following...
#Autowired
#Lazy
#Qualifer("someFacade_id1_source1")
SomeFacade someFacade;
but I can't find a way to influence the choice for the bean name in Spring, it seems there were some ideas Naming Strategy but those were abandoned and 'AnnotationBeanNameGenerator' decides the Bean Name I can' influence this procedure...
Any idea how to achieve what I like to do?
You can add a qualifier name to your bean and then use it to pick the bean you want.
Something like this should work:
#Configuration
class Config {
#Bean(name = "someFacade_id1_source1")
#Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public ReceptionFacade someFacade(String id, String source) {
return new SomeFacade(id, source);
}
}
#Service
class SomeService {
#Autowired
#Lazy
#Qualifer("someFacade_id1_source1")
SomeFacade someFacade;
}

How to dynamically create spring beans based on properties file and then autowired them to use in another bean?

I want to create beans after reading some properties from the application.yaml file and then want to inject them to other beans. How this can be achieved?
You might want to use #Value annotation to inject properties from application.yaml as fields into your class.
You probably need to create your bean on your own, e.g.:
#Bean
public YourBeanClass createBean() {
return new YourBeanClass()
}
You can then inject properties from your application.yaml with the #Value annotation in the bean creation method:
#Bean
public YourBeanClass createBean(#Value("${path.to.key}") String propertyValue) {
return new YourBeanClass(propertyValue)
}
When you create a bean like that, you can simply autowire it, e.g. in a service:
#Service
public class ServiceName {
public ServiceName(YourBeanClass autowiredType) {
}
}
And the bean YourBeanClass will be autowired into the constructor of your ServiceName service class for usage. The dependency resolution will be done by spring automatically.
Here's an example, that creates a bean for each value in a property list. This creates a different number of implementations depending on property values:
#Configuration
public class MineralTypeCreator {
#Bean
public List<MineralType> mineralTypes(final MineralProperties mineralProperties) {
return mineralProperties.getTypeIds().stream().map(GenericMineralType::new).collect(Collectors.toList());
}
private class GenericMineralType implements MineralType {
public GenericMineralType(final String id) {
this.id = id;
}
// ...
Having the properties passed into the #Bean-method is still nice, even if you only need to create a single bean.

When to use Qualifier and Primary in Spring

I have read that #Qualifier can be used in Injection phase whereas #Primary is used in Configuration phase. Am still unclear when to use which.
Also I have below doubts
can #Primary and #Qualifier be used together? if yes does #Qualifier take precedence?
can #Primary be used with #Autowired?
How is the Injection phase different from Configuration phase, this in respect to Spring beans
#Primary indicates that a bean should be given preference when multiple candidates
are qualified to autowire a single-valued dependency.
#Qualifier indicates specific bean should be autowired when there are multiple candidates.
For example, we have two beans both implement the same interface.
public interface BeanInterface {
String getName();
}
public class Bean1 implements BeanInterface {
#Override
public String getName() {
return "bean 1";
}
}
public class Bean2 implements BeanInterface {
#Override
public String getName() {
return "bean2";
}
}
Here is our service.
#Service
public class BeanService {
#Autowired
private BeanInterface bean;
}
And our configuration.
#Configuration
public class Config {
#Bean("bean1")
public BeanInterface bean1() {
return new Bean1();
}
#Bean("bean2")
public BeanInterface bean2() {
return new Bean2();
}
}
When Spring starts, it will find there are two beans("bean1" and "bean2") both can be autowired to BeanService since they implement the same interface BeanInterface. It reports an error in my Idea.
Could not autowire. There is more than one bean of 'BeanInterface' type.
Beans: bean1   (Config.java)
bean2   (Config.java)
And without a hint, Spring does not know which one to use.
So in our case, when we add #Primary to Config.bean1().
#Bean("bean1")
#Primary
public BeanInterface bean1() {
return new Bean1();
}
It tells Spring, "when you find more than one beans that both can be autowired, please use the primary one as your first choose." So, Spring will pick bean1 to autowire to BeanService.
Here is another way to autowire bean1 to BeanService by using #Qualifier in BeanService.class.
#Service
public class BeanService {
#Autowired
#Qualifier("bean1")
private BeanInterface bean;
}
#Qualifier will tell Spring, "no matter how many beans you've found, just use the one I tell you."
So you can find both #Qualifier and #Primary are telling Spring to use the specific bean when multiple candidates are qualified to autowire. But #Qualifier is more specific and has high priority. So when both #Qualifier and #Primary are found, #Primary will be ignored.
Here is the test.
#Configuration
public class Config {
#Bean("bean1")
#Primary
public BeanInterface bean1() {
return new Bean1();
}
#Bean("bean2")
public BeanInterface bean2() {
return new Bean2();
}
}
#Service
public class BeanService {
#Autowired
#Qualifier("bean2")
private BeanInterface bean;
#PostConstruct
public void test() {
String name = bean.getName();
System.out.println(name);
}
}
The output is "bean2".
Also, need to remember that #Qualifier as bigger priority then #Primary, that's means that it's waste to define both of the annotations.
#Primary means default implementation, while #Qualifier is the specific implementation.
You can review my blog I wrote regarding this annotations -
http://shaikezam.com/#/spring_qualifier
Yes, #Qualifier takes precedence.
Yes we can user #Primary and #Autowired together.
#Configuration Class related to Application Context which can be use to configure application level configuration.
To access beans with the same type we usually use #Qualifier(“beanName”) annotation. We apply it at the injection point along with #Autowired. In our case, we select the beans at the configuration phase so #Qualifier can't be applied here.
To resolve this issue Spring offers the #Primary annotation along with #Bean annotation.
Source

When autowiring use would be beneficiary with example

I have recently learned concept of autowiring in spring. When I was trying to understand in which particular scenarios spring autowiring can be useful
I came up with the below two reasons from one of the questions asked in our stakoverflow forum.
1.I wanted to read values from a property file and inject them into a bean. Only way I could figure out how to do this at start up of my app was to
wire the bean in XML (and inject the properties.) I ended up using the "byName" attribute (because the bean was also marked as #Component) and then
used #Autowired #Qualifier("nameIChose") when injecting the bean into another class. It's the only bean I've written that I wire with XML.
2.I've found autowiring useful in cases where I've had a factory bean making another bean (whose implementation class name was described in a system
property,so I couldn't define the all wiring in XML). I usually prefer to make my wiring explicit though;
Can any body please give me some code snippet example of the above situations that would make my understanding of autowiring more clearer?
Here is an example of injecting properties into a bean.
Using field injection:
#Component
public class YourBean {
#Value("${your.property.name}")
private String yourProperty;
}
Using constructor injection:
#Component
public class YourBean2 {
private String yourProperty;
#Autowired
public YourBeans2(#Value("${your.property.name}") String yourProperty) {
this.yourProperty = yourProperty;
}
}
The following is a super simple example of autowiring various beans
#Component
public class Foo {
public void doSomething() {
}
}
#Component
public class Bar {
private Foo foo;
#Autowired
public Bar(Foo foo) {
this.foo = foo;
}
public void doSomethingElse() {
foo.doSomething();
}
}
In the previous example, no XML configuration of Foo and Bar needs to be done, Spring automatically picks up the beans because of their #Component annotation (assuming of course that component scanning has been enabled)

Autowiring doubts in spring?

After going thru autowiring concept
i have got some questions. These are:-
If i need to autowire below class byType or byName , is it mandatory to have setStudent() method in class College?
public class College {
private Student student1;
private String registration1;
}
<bean id="student1" class="Student"/> - in case of byname it will look into id attribute and in case of bytype it will look for class attribute in above
Stetement. Right? If incase it finds two bean dean tags for the same type it will throw fatal error in case of bytype. Correct?
autodetect Scenario chooses constructor or byType through introspection of the bean class. If a default constructor is found, the byType mode
will be applied.
My question here if default constructor is not found and constructor with argument is found then autowire by constructor
will be applied. Correct?
Do we need to specify #Autowired somewhere in College to apply the autowiring. As i can see this in this example
but nothing is specified here
1), 4) There are two separate ways of autowiring in Spring: XML-based and annotaion-based.
XML-based autowiring is activated from XML config, as described here. In the end, it will call setter method, so setStudent() method is required here.
Annonation-based autowiring, on the other hand, is performed via reflection magic. It attempts to fill everything you mark with #Autowired annotation. In fact, it can set private field with no accessors, as in
public class Foo {
#Autowired private Thingy thing; // No getThing or setThing methods
private void doStuff() {
// thing is usable here
}
}
For #Autowired annotaion to work, you will need to define corresponding bean post-processor; it is done by adding the following line to xml config:
<context:annotation-config/>
Note, that these two autowiring methods are independant, and it is possible(but not recommended) to use them simultaneously. In that case, xml autowiring will override annotations.
2) In general, autowiring will fail, if it cannot find one and only one candidate for injection. So, in your case, it will fail with exception upon container creation. There are some fallback quirks, but in general it works reliably.
3) Yes, documentaion says so.
About byName and byType autowiring. While byName autowiring simply tries to match bean name (can be specified with id attribute), byType is a bit more complex than class attribute lookup. It searches beans by type, and it will match interfaces. Example:
public interface SomeService {
void doStuff();
}
public class SomeServiceImpl implements SomeService {
#Override public void doStuff() {
// Implementation
};
}
public class ServiceUser {
#Autowired
private SomeService someService; // SomeServiceImpl instance goes here
}
P.S. You are referencing two different versions of Spring in your question, 2.5 and 3.0. Autowiring behavior is same in both.
In Addition if you are using #Autwired annotation you need to mark the classes as candidates for autowiring. It should be done by using one of these annotations:
#Repository
#Service
#Component
#Controller
and of cause you can configure it in different scopes:
#Scope("prototype")
#Repository
public class MovieFinderImpl implements MovieFinder {
// ...
}
Hope it makes it more clear.

Resources