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.
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>
parent class is like this:
public class BaseDAO{
private DBRoute defaultDB;
public DBRoute getDefaultDB()
{
return this.defaultDB;
}
public void setDefaultDB(DBRoute defaultDB)
{
this.defaultDB = defaultDB;
}
}
I have create beans like below:
<bean id="adsConfigDB" class="net.flyingfat.common.dbroute.config.DBRoute">
<constructor-arg value="adsConfig" />
</bean>
<bean id="adsBizDateDB" class="net.flyingfat.common.dbroute.config.DBRoute">
<constructor-arg value="adsBizDate" />
</bean>
I want to inject superclass property defaultDB in subclass through byName, not byType, which is in subclass inject defaultDB using adsConfigDB or adsBizDateDB. Is there any way to do this with spring annotations? I already tried Autowired or Resource with constructor which doesn't work. By the way, I already know this can be done using XML.
#Qualifier annotation – This annotation is used to avoid conflicts in bean mapping and we need to provide the bean name that will be used for autowiring. This way we can avoid issues where multiple beans are defined for same type. This annotation usually works with the #Autowired annotation. For constructors with multiple arguments, we can use this annotation with the argument names in the method.
Your code will be like this..
#Autowired
#Qualifier("adsConfig")
private DBRoute defaultDB;
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;
I have been tasked with updating a old project that I did not write.
The project is Spring MVC based and has an older Spring Controller configuration that I am unfamiliar with.
The controllers have bean configurations as follows
<bean id="controllerName" class="the.project.controller.class">
<property name"serviceName">
<ref bean="serviceName">
</property>
<property name"successView">
<value>viewName</value>
</property>
</bean>
where serviceName refers to a class annotated with #Service as follows
#Service(value=serviceName)
Is this the correct replacement for the xml configuration ?
#Autowired
#Qualifier("serviceName")
ServiceNameImpl serviceName
thanks
edit here is the organization of the serviceName class and interface
public interface ServiceName {
// methods omitted
}
#Service(value="serviceName")
public class ServiceNameImpl implments ServiceName {
//methods omitted
}
The #Resource annotation is not available to me ( Spring 3.0.7) and Autowire as above fails ( as it appears the type is not as expected as described below )
org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching beans of type [the.project.ServiceNameImpl] found for dependency
Given the edits, what am I doing wrong here ( Apologies for leaving out this information )?
in the end I need to be able to access the methods of the interface and its implementation
for example
serviceName.doSomething(someVar);
That's correct, but consider using private modifier for serviceName. Another way would be to use #Resource:
#Resource
private ServiceNameClass serviceName;
Note that in this case you don't need a #Qualifier("serviceName") - #Resource autowires by (field) name while #Autowired uses type by default. Only a problem when you have several beans of the same/compatible type.
Also you can skip the controllerName bean definition altogether by annotating controller class with #Controller.
BTW you can also shorten the XML configuration a bit by using the following syntax:
<bean id="controllerName" class="the.project.controller.class">
<property name"serviceName" ref="serviceName"/>
<property name"successView" value="viewName"/>
</bean>
(IntelliJ suggests this transformation and performs it for you).
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.