So for some reason half our project's beans are marked with #Component and injected into other objects marked #Component with the #Autowired annotation, while the other half is wired up explicitly with appliciationContext.xml bean declarations and properties with ref beans values.
Question is, in those xml bean declarations, can I inject one of the objects marked #Component? If so, what will its bean reference name be?
For example;
Some classes are annotated like so;
#Component
public class BeanAImpl{ ... }
Then in applicationContext.xml other classes are wired explicitly as they are not annotated;
<bean id="beanB" class="com.myapp.BeanBImpl"></bean>
Can I inject both 'kinds' of beans in applicationContext.xml?
<bean id="beanUser" class="com.myapp.BeanUserImpl">
<property name="beanA">HOW_TO_GET_REF_TO_BEANA?</property>
<property name="beanB"><ref bean="beanB"/></property>
</bean>
Default name for #Component of type BeanAImpl is beanAImpl, you can use it in XML as you do with manually declared beans (also note that <property> allows shorter syntax):
<property name="beanA" ref = "beanAImpl" />
Alternatively, you can explicitly set a name as #Component("beanA").
Here is what Spring says:
When a component is autodetected as part of the scanning process, its bean name will be generated by the BeanNameGenerator strategy known to that scanner.
If you don't want to rely on the default bean-naming strategy, you may provide a custom bean-naming strategy. First, implement the BeanNameGenerator interface, and be sure to include a default no-arg constructor. Then, provide the fully-qualified class name when configuring the scanner:
<context:component-scan base-package="org.example"
name-generator="org.example.MyNameGenerator" />
The deafault implementation is just the class name starting with loer case.
Instead of #Component, I think you want to use #Resource(name="your_id_here"), and then you can <ref> it like you're doing with beanB. Give it a shot.
Source: http://static.springsource.org/spring/docs/3.0.0.M3/reference/html/ch04s11.html#beans-resource-annotation
Related
I have some code that generates a class from an interface. I need to reference that interface in a Spring XML configuration. Is there a Spring 3 annotations I can use on the interface such that I can reference the generated implementation using <constructor-arg ref="myBeanInterface"/>?
I can reference it using <constructor-arg value="com.mysite.myBeanInterface"/>, however I want to refrence a bean name instead of an explicit class.
Details: The beans are generated by an extension of AbstractFactoryBean. I do not have access to the bean generating code.
Use the name of your factory bean. If you have something like:
<bean id="myBean class="MyBeanInterfaceFactoryBean>
...
</bean>
Then to inject the bean that was generated by the factory bean, just use myBean.
I need to inject a object of a java class in spring controller through applicaionContext.xml. My controller will be ,
#Controller
public class SpringController{
private MyClass obj;
}
I know I can do it with #Autowired annotation.
Is this really good to create a object for a controller through applicaionContext.xml ? Also can I inject a object of a class in controller using the <property> tag inside a <bean> tag ?
Is this really possible ? or please forgive me if it is a stupid question.
I need to know the possible ways for how to inject a object of a class in Spring controller ?
You can of course use #Autowired annotation to autowire the relationships, which can reduce the need to define the properties and constructor arguments for the controller in your applicationContext.xml file. And also to add a dependency to a class, you don't need to modify the configuration files.
But it has some disadvantages too, like if you use #Autowired, there will not be any explicit documentation for the wiring details between Spring managed beans. And to know the relationships between the beans, you have to go through your managed beans. But, if you use configuration files to define the relationships, the relationship details can be found in one place.
You can inject an object of a class into your controller through your applicaionContext.xml as below:
Constructor based injection:
#Controller
public class SpringController{
private MyClass obj;
public SpringController(MyClass obj){
this.obj=obj;
}
}
<bean id="myClassImpl" class="x.y.z.MyClassImpl"></bean>
<bean id="springController" class="x.y.z.web.controllers.SpringController">
<constructor-arg ref="myClassImpl"></constructor-arg>
</bean>
Setter based injection:
#Controller
public class SpringController{
private MyClass obj;
public void setObj(MyClass obj){
this.obj=obj;
}
public MyClass getObj(){
return obj;
}
}
<bean id="myClassImpl" class="x.y.z.MyClassImpl"></bean>
<bean id="springController" class="x.y.z.web.controllers.SpringController">
<property name="obj" ref="myClassImpl"></property>
</bean>
If you want to inject an object in a controller and you particularly want to you use xml,then instead of component scanning of Controller you should create a bean of the controller class of singleton scope in the application context.
Your controller class need not be annotated with #Controller.
you then have to you extend some Controller also like AbstractCommandController, AbstractController, AbstractFormController, AbstractWizardFormController, BaseCommandController, CancellableFormController, MultiActionController SimpleFormController, UrlFilenameViewController
Now to inject a particular object you can use Either Constructor and Setter based injection.
or you can use Autowring by name or type to auto inject the object.
Make sure that you have also declared the bean of that object also in Application Context.
After a DispatcherServlet has received a request and has done its work to resolve locales, themes and suchlike, it then tries to resolve a Controller, using a HandlerMapping. When a Controller has been found to handle the request, the handleRequest method of the located Controller will be invoked; the located Controller is then responsible for handling the actual request and - if applicable - returning an appropriate ModelAndView.
Thats it.
Actually, injection with xml and annotation is same behind the scene. Xml is old fashion while annotations are newer.
Basically, there are 2 types of injection types.
byName
Autowiring by property name. Spring container looks at the properties
of the beans on which autowire attribute is set to byName in the XML
configuration file. It then tries to match and wire its properties
with the beans defined by the same names in the configuration file.
You can give explicit names to beans both with xml and annotation.
#Service("BeanName")
#Component("BeanName")
#Controller("BeanName")
<bean name="BeanName" class="someclass"></bean>
and inject beans by using #Qualifier annotation.
#Autowired
#Qualifier("BeanName")
and with xml
<bean id="MyBean2" class="MyBean2 class">
<property name="Property of MyBean2 which refers to injecting bean" ref="BeanName" />
</bean>
byType
Autowiring by property datatype. Spring container looks at the
properties of the beans on which autowire attribute is set to byType
in the XML configuration file. It then tries to match and wire a
property if its type matches with exactly one of the beans name in
configuration file. If more than one such beans exists, a fatal
exception is thrown.
Default auto wiring mode is byType, so spring will look for matching type in auto wiring. However, older versions of Spring has default behavior none on injection. If you want to inject byType using xml, you should tell spring contaioner explicitly.
For example MyBean2 has a reference to MyBean, by setting autowired attribute to byType it handles injection automatically.
<bean id="MyBean" class="MyBean class">
<property name="Property of MyBean2 which refers to injecting bean" ref="BeanName" />
</bean>
<bean id="MyBean2" class="MyBean2 class"
autowire="byType">
</bean>
It also depends on where the injection take place in your code. There are 2 types, setter getter injection and constructor injection.
Note : There is no difference in #Controller since they are already in spring context.
See also
Spring Beans Auto wiring
I ran into such problem. I was getting "Ambiguous mapping found". (I use xml configuration as well and i am injecting a bean into my controller)
Then looking at my console i realized that my controller was being instantiated twice.
In more detailed look i noticed that my annotation
#Controller(value = "aController")
(Note value = "aController")
was different from my xml configuration where i was instatiating the same controller with different bean id
<bean id="aControleRRRRR" class="package.ControllerClassName"
p:property-ref="beanToInject" />
(Note id="aControleRRRRR")
So in conclusion your #Controller name (value = "aController") needs to be exactly the same as the name you give in the XML configuration (id="aControleRRRRR"), so that Spring can manage to distinct that they refer to the same bean (instance)
Hope this helps
I am confused between ref and depends-on attribute in Spring.I read the spring doc but I am still confused.I wish to know the exact difference between the two and in which case which one shall be used.
From the official documentation: http://docs.spring.io/spring/docs/3.2.x/javadoc-api/org/springframework/context/annotation/DependsOn.html
Beans on which the current bean depends. Any beans specified are guaranteed to be created by the container before this bean. Used infrequently in cases where a bean does not explicitly depend on another through properties or constructor arguments, but rather depends on the side effects of another bean's initialisation.
Perhaps an example of a situation where depends-on is needed would help. I use Spring to load and wire my beans. Here is an example bean definition:
<bean id="myBean" class="my.package.Class">
<property name="destination" value="bean:otherBeanId?method=doSomething"/>
</bean>
<bean id="otherBeanId" class="my.package.OtherClass"/>
Notice that the property value is a string, which references otherBeanId. Because of the way this variable is resolved, Spring doesn't learn of the dependency, so it may destroy otherBeanId then myBean. This may leave myBean in a broken state for a little while.
I can use depends on to fix this problem as follows:
<bean id="myBean" class="my.package.Class" depends-on="otherBeanId">
<property name="destination" value="bean:otherBeanId?method=doSomething"/>
</bean>
There might be a situation where a bean might be a property in another bean i.e; the property bean is directly involved in the bean definition as a property in such case we refer the beans with ref attribute.
There might be a situation where in a bean instantiation is required for the other bean to be successfully created, the other bean is not a property of the bean under definition, in such case we make use of the depends-on attribute.
<beans default-autowire="byType" />
means that all fields of beans will automatically have dependencies injected if there is no more than 1 bean with the desired type.
I wonder if there is a way to define some sort of priority order (based on naming convention for example) for the auto-wiring in the case where there are more than one bean of the desired type.
Thanks in advance.
Edit: I just want to add that i'm not allowed to use annotations such as #Component and #Qualifier in the project i'm currently working on.
No there is not, but you can override this behavior as needed for each bean e.g.specify something like this where required:
<beans default-autowire="byType" >
<bean id="..." autowire="byName">
....
</bean>
</beans>
From spring 2.5 upwards when using the <context:component-scan/> to autowire beans via #Autowired you can also add #Qualifier where needed to specify a bean by name if there are multiple beans of the same type.
As stated in the spring documentation there are a few different ways to specify autowiring:
no - do not autowire, this is the default
byType - property type must match bean type, if more than one bean of that type is exists then an exception is thrown
byName - bean name must match property name
constructor - basically the same as byType but for constructors, spring picks the constructor with the most matches
autodetect - same as byType unless there is no default constructor where it falls back to constructor autowiring
Normally dependencies are injected via setters by the following configuration (http://static.springsource.org/sprin...beans-beanname) :
<bean id="exampleBean" class="examples.ExampleBean">
<!-- setter injection using the nested <ref/> element -->
<property name="beanOne"><ref bean="anotherExampleBean"/></property>
<!-- setter injection using the neater 'ref' attribute -->
<property name="beanTwo" ref="yetAnotherBean"/>
<property name="integerProperty" value="1"/>
</bean>
<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>
Lets say the class examples.ExampleBean has a collection listeners objects, and the method addListener(SomeListenerInterface) is the only possible way add listeners. Can I inject listeners declaratively in xml like its done with property setters?
You could probably conjure up some baroque mechanism for doing this all in XML, but the cleanest way to do this is to use a FactoryBean. You write a class which implement FactoryBean, and which is responsible for constructing and configuring your target object (see Spring docs). Your FactoryBean would have the required getters/setters/autowiring, and injects them into the target object.
This is often the cleanest way to handle non-javabeans in Spring, particularly if you cannot modify the target class.
Here goes property Element definition
Property elements correspond to JavaBean setter methods exposed by the bean classes.
To get your goal, you can use #Autowired annotation. It works even when using an arbitrary name
#Autowired
public void inject(SomeListenerInterface someListenerInterface) {
this.someListenerInterface = someListenerInterface;
}