Spring-configuration: I have created 2 beans with reference to same class but different database sessions.
<bean id="abc1" class="abc">
<bean id="abc2" class="abc">
Now is there any way to set bean with id "abc1" as default bean for autowiring and use abc2 for autowiring when mentioned explicitly like this:
#Autowiring
#Qualifier("abc2")
private abc obj;
Solution:
<bean id="abc1" class="abc" primary="true">
makes abc1 default one to be autowired.
for creating an instance of abc2, we can use this:
#Autowired
#Qualifier("abc2")
private abc obj;
The #primary annotation or primary attribute of xml is used exactly for that purpose. Here is the details of the same. It is pretty well documented here.
http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/annotation/Primary.html
So if you mention <bean id="abc1" class="abc" primary="true"/> it will get priority over abc2, and you can use #Qualifier for abc2 wherever you need. Hope this helps.
If you skip the #Qualifier annotation, then Spring will lookup for a bean with the same name as the private member. For example:
#Autowired
private abc abc1; //Spring will search for a bean with id="abc1"
This was you can use abc1 as a default value.
If you don't want to make Spring search for a specific bean, then you can trigger the #Qualifier and then Spring will not care how the member is called, but will assign it's value to refer to the bean that has the same id pointed out in the #Qualifier annotation:
#Autowired
#Qualifier("abc2")
private abc theNameDoesNotMatter;
Related
I would like to ask if there is possible in spring to annotate class with #Service with more than 1 value, something like this:
#Service({"ServiceName1","ServiceName2"})
public class ClassName {
}
The reason is i want to get same class when i am calling applicationContext.getBean("ServiceName1"); or applicationContext.getBean("ServiceName2");
Thanks in advance for answers.
You can just declare your bean in a configuration class instead, and specify multiple names in the Bean annotation:
#Bean(name = { "ServiceName1", "ServiceName2" })
public ClassName myService() {
return new ClassName();
}
But if you're getting beans by name, from the application context, you've probably missed the whole point of dependency injection.
I think if we use #Component/ #Service annotations we can create only one bean instance for a class. If we need to create multiple beans for a single class we need to go with xml approach. Define the beans for the single Class in applicationContext.xml
<bean id="ServiceName1" class="<ClassName Path>">
</bean>
<bean id="ServiceName2" class="<ClassName Path>">
</bean>
In Spring XML config, I can use the ref="bean_name" syntax to refer to a bean by ID or name.
<bean id="petStore" class="org.springframework.samples.jpetstore.services.PetStoreServiceImpl">
<property name="accountDao" ref="accountDao"/>
</bean>
Is there an equivalent way of achieving this in Java config, using the name attribute on the #Bean annotation? I've used the #Named annotation (javax.inject.Named) and have seen #Qualifier suggested elsewhere, but is a separate annotation really necessary if we already have a name attribute on the #Bean annotation?
#Qualifier is the correct thing to use here.
#Autowired
#Qualifier("bean_name")
private Beantype var;
And declaring your component
#Component(value = "bean_name")
public class Beantype {...}
At least that works for me.
I have created few singleton bean in spring. I added log inside constructor. I could see log is getting printed twice.
#Component
public class User{
public User() {
System.out.println(" Bean got initialized"+this);
}
private Integer userid;
private String username;
//getter and setter
}
I have defined bean in XML and configured auto-scan.
<context:component-scan base-package="com.demo" />
<bean id="user" class="com.demo.User"/>
Since I have initialized bean in context xml and package scan, bean is getting initialized twice. After removing #Component from class, I am seeing only once log.
Please confirm my understanding is correct or not?
That's correct; the component scan will pick it up, and then you explicitly create another copy.
#Component annotation was introduced in spring 2.5 in order to get rid of XML bean definition by using classpath scanning. if the class is annotated with #Component, it will auto detected in the classpath scanning and an instance will be created(instantiated). Since #Component does the job for creating the bean, you do not have to declare the bean in XML. So remove the XML bean declaration. so it will not create duplicate objects.
Note: if you do the annotation based bean declaration with #Component, you do not need to use XML based declaration as you have done. If you are doing the XML based bean declaration, you do not need to do the annotation based bean declaration. So make sure that you declare only one of these options. not with both.
With Spring it is possible to inject a list of beans by the interface class like:
#Component
public class Service {
#Autowire
private List<InterfaceType> implementingBeans;
...
}
All defined beans that implement this interface will be present in this List.
The annotation based approach is not possible for me, as the Service class is in a module that must not have spring dependencies.
I need to use this mechanism from outside via xml configuration.
<bean id="service" class="...Service">
<property name="implementingBeans">
??? tell spring to create a list bean that resolves all beans of the interfaceType.
</property>
</bean>
Does anyone know how to solve this?
EDIT: Additionally, there are more than one spring applications that use this service. So the best solution would be to handle this szenario completely via xml configuration. I can then copy the xml parts to all spriong applications that need this.
I want to avoid having a kind of initializer bean that gets the service injected and must then be copied to all spring applications.
Kind regards.
An XML-only solution would simply have you declare a <bean> of the "external" type and provide an autowire value of "byType".
Controls whether bean properties are "autowired". This is an
automagical process in which bean references don't need to be coded
explicitly in the XML bean definition file, but rather the Spring
container works out dependencies.
[...]
"byType" Autowiring if there is exactly one bean of the property type in the container. If there is more than one, a fatal error is
raised, and you cannot use byType autowiring for that bean. If there
is none, nothing special happens.
The explanation is a little confusing in that we expect multiple InterfaceType beans, but the actual field is of type List and Spring will be able to dynamically instantiate one and add all the InterfaceType beans to it, then inject it.
Your XML would simply look like
<bean id="service" class="...Service" autowire="byType">
</bean>
My original suggested solution made use of SpEL.
In the module that does have Spring dependencies, create a DTO
#Component(value = "beanDTO")
public class BeanDTO {
#Autowire
private List<InterfaceType> implementingBeans;
public List<InterfaceType> getImplementingBeans() {
return implementingBeans;
}
}
and then use SpEL to retrieve the value of implementingBeans from the beanDTO bean.
<bean id="service" depends-on="beanDTO" class="...Service">
<property name="implementingBeans" value="{beanDTO.implementingBeans}" />
</bean>
Spring will create the BeanTDO bean, inject all the beans that are of type InterfaceType. It will then create the service bean and set its property from beanDTO's implementingBeans property.
Following comments on question:
In an effort to be more JSR 330 compliant, Spring has introduced support for Java EE's javax.inject package. You can now annotate your injection targets with #javax.inject.Inject instead of #Autowired. Similarly, you can use #Named instead of #Component. The documentation has more details.
Maybe, because of my wrong English, I couldn't understand the benefit of using #Autowired annotation.
According to the tutorial we can simplify the first(I.) case to second case(II.) by means of #Autowired.
My question is, what is the meaning of the #Autowired ? Because it doesnt tell any more, since without using #Autowired the compiler can figure out that "EmpDao emDao" and "EmpManager" are closely related according the declaration.
code cited from here
I.
<bean id="empDao" class="EmpDao" />
<bean id="empManager" class="EmpManager">
<property name="empDao" ref="empDao" />
</bean>
public class EmpManager {
private EmpDao empDao;
public EmpDao getEmpDao() {
return empDao;
}
public void setEmpDao(EmpDao empDao) {
this.empDao = empDao;
}
...
}
II.
<context:annotation-config />
<bean id="empManager" class="autowiredexample.EmpManager" />
<bean id="empDao" class="autowiredexample.EmpDao" />
import org.springframework.beans.factory.annotation.Autowired;
public class EmpManager {
#Autowired
private EmpDao empDao;
}
#Autowired is spring-specific. #Inject is the standard equivallent. It is an annotation that tells the context (spring, or in the case of #Inject - any DI framework) to try to set an object into that field.
The compiler has nothing to do with this - it is the DI framework (spring) that instantiates your objects at runtime, and then sets their dependencies at the points you have specified - either via XML or via an annotation.
I agree it is a possible scenario for a DI framework to try to inject dependencies into all fields, even if they are not annotated. (And if you want to exclude a particular field, to annotate it). But they chose the other strategy (configuration-over-convention). By the way:
if using xml config and choose some form of autowiring, the dependencies of the bean will be automatically autowired without the need to specify anything
you can specify per-context autowiring settings.
When the server bootstraps itself. It finds
<context:annotation-config />
in the application context and then goes through the classes defined in the contexts. If there are any beans that are autowired, it injects that into the class by referring the context file.
Basically, it promotes convention over configuration. That's what most frameworks do these days to reduce the development time.
the #Autowired Spring annotation tells Spring to for a bean named 'empDao' and inject it into the EmpManager class, without you having to add the empDao bean as a property in your spring config file.
#Autowired tells Spring to find a bean of the declared type and wire in that bean, rather than requiring an explicit lookup by bean name. It can, under certain circumstances, make configuring applications easier if you only have one implementation of your types in a given Spring context.