In the posts so far we have been defining our beans and configuring them using configuration files. However this results in very large XML files. Spring allows the properties of beans to be automatically wired based on the name of the property or some other conditions.
Spring supports four kind of autowiring:
All the beans that we create have names(or ids). If for a bean, the name of the property matches that of the bean, then the property will be wired with that bean reference.Consider the sample car implementation:
We have used the p-namespace to further shorten the XML.
I created the below sample code to test the above bean:
I changed the type of leatherSeating bean to Engine class
Also if we have multiple objects of CarByName class and all are autowired by name, then all the objects will end up with the same engine and seating objects configured.
Spring supports four kind of autowiring:
- autowire by name
- autowire by type
- autowire by constructor
- auto detect
public interface ICar { public String describe(); }I also created a couple of other simple classes to use as properties for the Car implementations:
public class Engine { private String name; public void setName(String name) { this.name = name; } public String getName() { return name; } @Override public String toString() { return "Engine - " + super.toString() + " and name " + this.getName(); } }
package com.car; public class Seating { private String color; public void setColor(String color) { this.color = color; } public String getColor() { return color; } @Override public String toString() { return "seating - " + super.toString() + " of color " + this.getColor(); } }autowire by name:
All the beans that we create have names(or ids). If for a bean, the name of the property matches that of the bean, then the property will be wired with that bean reference.Consider the sample car implementation:
public class CarByName implements ICar { private Engine combustEngine; private Seating leatherSeating; public Engine getCombustEngine() { return combustEngine; } public void setCombustEngine(Engine combustEngine) { this.combustEngine = combustEngine; } public Seating getLeatherSeating() { return leatherSeating; } public void setLeatherSeating(Seating leatherSeating) { this.leatherSeating = leatherSeating; } @Override public String describe() { return "Car is " + this + ", engine is " + this.getCombustEngine()
+ " and seating is " + this.getLeatherSeating(); } }The CarByName class has two properties a combustEngine and leatherSeating. To ensure that the class is autowired by name:
<bean id="carByName" class="com.car.CarByName" autowire="byName"/> <bean id="combustEngine" class="com.car.Engine" p:name="Combusto" /> <bean id="leatherSeating" class="com.car.Seating" p:color="red" />As can be seen, we have created two beans with the names that match the properties. Also for the "carByName" bean we have removed the property/constructor-arg elements. Instead we have added an autowire property with the value "byName".
We have used the p-namespace to further shorten the XML.
I created the below sample code to test the above bean:
public static void main(String[] args) { final BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("autowired-beans.xml")); CarByName carByName = (CarByName) beanFactory.getBean("carByName"); System.out.println("Bean received is " + carByName.describe()); }The output is as below:
Bean received is Car is com.car.CarByName@872380, engine is Engine - com.car.Engine@2bb514 and name Combusto and seating is seating - com.car.Seating@17d5d2a of color redThe Spring Container instantiates the carByName bean. It then looks for beans with names that match the names of the properties. It instantiates the beans if necessary and configures the carByName bean using setter injection.
I changed the type of leatherSeating bean to Engine class
<bean id="leatherSeating" class="com.car.Engine" p:name="Combusto" />On trying to execute the above method, we now get the exception:
Exception in thread "main" org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'carByName' defined in class path resource
[autowired-beans.xml]: Initialization of bean failed; nested exception is
org.springframework.beans.ConversionNotSupportedException: Failed to convert
property value of type 'com.car.Engine' to required type 'com.car.Seating' for
property 'leatherSeating'; nested exception is java.lang.IllegalStateException:
Cannot convert value of type [com.car.Engine] to required type [com.car.Seating]
for property 'leatherSeating': no matching editors or conversion strategy found
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.
doCreateBean(AbstractAutowireCapableBeanFactory.java:527)
Spring needs to find Beans of the same type as the property and with the same name, else the bean creation fails.Also if we have multiple objects of CarByName class and all are autowired by name, then all the objects will end up with the same engine and seating objects configured.
No comments:
Post a Comment