Bean autowiring :
Auto-wiring is a feature which helps us skip some of the configurations that we have to do by internally injecting the object dependency. It uses setter or construction injection to do it.
Consider the example below. Class Triangle has a property which is a list of objects of type Point.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
package com.j2eereference.spring; import java.util.ArrayList; import java.util.List; public class Triangle { List<Point> points = new ArrayList<Point>(); public void draw() { for(Point point:points) { System.out.println("Point = ("+point.getX()+","+point.getY()+")"); } } } |
The bean configuration for this would be:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="triangle" class="com.j2eereference.spring.Triangle"> <property name="points"> <list> <ref bean="zeroPoint" /> <ref bean="point1" /> <ref bean="point2" /> </list> </property> </bean> <bean id="zeroPoint" class="com.j2eereference.spring.Point"> <property name="X" value="0" /> <property name="Y" value="0" /> </bean> <bean id="point1" class="com.j2eereference.spring.Point"> <property name="X" value="20" /> <property name="Y" value="0" /> </bean> <bean id="point2" class="com.j2eereference.spring.Point"> <property name="X" value="0" /> <property name="Y" value="30" /> </bean> </beans> |
Notice that the property “points” is initialized using the reference beans “zeropoint”, “point1” and “point2”. This kind of configurations can be skipped using auto-wiring.
There are 3 types auto-wiring
Autowiring ByName :
When the names of the bean ids match the names of the member variables of the bean which has a dependency , we can auto-wire beans based on name by setting autowire=”byName” .
Triangle.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
package com.j2eereference.spring; public class Triangle { private Point pointA; private Point pointB; private Point pointC; public Point getPointA() { return pointA; } public void setPointA(Point pointA) { this.pointA = pointA; } public Point getPointB() { return pointB; } public void setPointB(Point pointB) { this.pointB = pointB; } public Point getPointC() { return pointC; } public void setPointC(Point pointC) { this.pointC = pointC; } public void draw() { System.out.println("PointA = ("+pointA.getX()+","+pointA.getY()+")"); System.out.println("PointB = ("+pointB.getX()+","+pointB.getY()+")"); System.out.println("PointA = ("+pointC.getX()+","+pointC.getY()+")"); } } |
spring.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="triangle" class="com.j2eereference.spring.Triangle" autowire="byName> </bean> <bean id="pointA" class="com.j2eereference.spring.Point"> <property name="X" value="0" /> <property name="Y" value="0" /> </bean> <bean id="pointB" class="com.j2eereference.spring.Point"> <property name="X" value="20" /> <property name="Y" value="0" /> </bean> <bean id="pointC" class="com.j2eereference.spring.Point"> <property name="X" value="0" /> <property name="Y" value="30" /> </bean> </beans> |
DrawingApp.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
package com.j2eereference.spring; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class DrawingApp { /** * @param args */ public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml"); Triangle triangle = (Triangle)context.getBean("triangle"); triangle.draw(); } } |
Point.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
package com.j2eereference.spring; public class Point { private int X; private int Y; public Point() { super(); } public Point(int x, int y) { super(); X = x; Y = y; } public int getX() { return X; } public void setX(int x) { X = x; } public int getY() { return Y; } public void setY(int y) { Y = y; } } |
The member variables pointA, pointB and pointC match the names of the bean ids. Since the autowire is set to “byName” for the bean triangle, it internally references the bean ids pointA, PointB and pointC for the member variables.
Output:
PointA = (0,0)
PointB = (20,0)
PointC = (0,30)
Autowiring ByType :
This is achieved by setting autowire=”byType”. It works if the type of the of the member variables are unique. In this case, if the type of the member variable matches the class of the bean, then it is auto-wired by type. The limitation here is if there are more than one member variables of same type it wont work. Considering the above example, Triangle.java has 3 member variables of type Point. Hence auto-wring by type wont work in this case.
Autowiring ByConstructor :
It works same as auto-wire by name, but does constructor injection instead of setter injection by setting autowire=”constructor”. Suppose there is a class that has 3 member variables, each of different type and there is a constructor that accepts 3 parameters. There needs to be 3 beans configured for each type of member variables and autowire=”constructor”. Spring checks the type of the constructor arguments and matches with the beans defined for auto-wiring.
By default, auto-wire is off. We have to explicitly set this tag to use this feature.
Though auto wiring feature may look cool, it is difficult to debug in real world application where there are lot of beans and references if it is all auto-wired. Hence auto-wiring may be recommended for small application whereas explicit wiring is recommended for large applications.
[…] Bean autowiring […]