In this article, we will look into spring’s auto-wiring ability. I will show you examples of auto-wiring by type, name and the constructor.
auto-wiring is done using one of the below strategies.
byType
byName
constructor
no
You can either set the default-autowiring
attribute at beans
level or use the autowiring
at bean
level to set the auto-wiring strategy to one one of the above mentioned strategies.
Dependencies
Add the following dependencies:
spring-core
spring-context
spring-beans
pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.javarticles.jdbc.datasource</groupId> <artifactId>springdatasource</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${spring.version}</version> </dependency> </dependencies> <properties> <spring.version>3.2.3.RELEASE</spring.version> </properties> </project>
Auto-Wiring By Type
In testBean
definition, we have set autowire
to byType
.
autowireByTypeContext.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="testBean" class="com.javarticles.spring.TestBean" autowire="byType"> <constructor-arg type="java.lang.String" value="A" /> </bean> <bean id="type1" class="com.javarticles.spring.Type1"/> <bean id="type2ByName" class="com.javarticles.spring.Type2"/> </beans>
TestBean
has member variables type1ByType
and type2ByName
of type Type1
and Type2
. If you notice, we have not explicitly set the properties of of these member variables in the bean definition of TestBean
. We want spring to figure out automatically and auto-wire for us using the type as the matching strategy.
TestBean:
package com.javarticles.spring; public class TestBean { private String value; private Type1 type1ByType; private Type2 type2ByName; public TestBean(){} public TestBean(String value) { this.value = value; } public TestBean(Type1 type1, Type2 type2) { type1ByType = type1; type2ByName = type2; } public void setValue(String value) { this.value = value; } public Type1 getType1ByType() { return type1ByType; } public void setType1ByType(Type1 type1ByType) { this.type1ByType = type1ByType; } public Type2 getType2ByName() { return type2ByName; } public void setType2ByName(Type2 type2ByName) { this.type2ByName = type2ByName; } public String getValue() { return value; } }
Type1:
package com.javarticles.spring; public class Type1 { public String toString() { return "Type1"; } }
Type2:
package com.javarticles.spring; public class Type2 { public String toString() { return "Type2"; } }
AutowireByTypeExample:
package com.javarticles.spring; import org.springframework.context.support.ClassPathXmlApplicationContext; public class AutowireByTypeExample { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( "autowireByTypeContext.xml"); try { TestBean testBean = (TestBean) context.getBean("testBean"); System.out.println("testBean.type1's value: " + testBean.getType1ByType()); System.out.println("testBean.type2's value: " + testBean.getType2ByName()); } finally { context.close(); } } }
You can see spring managed to find the properties by type and set them to the bean.
Output:
testBean.type1's value: Type1 testBean.type2's value: Type2
Auto-Wiring By Name
In this example, spring will use the name of the member variable to find the respective beans and wire them to the TestBean
. Since we have a bean for type2ByName
, it will manage to set type2ByName
member variable but since there is no bean for type1ByType
it will not be able to set the bean and TestBean.getType1ByType()
should return us null.
autowireByNameContext.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="testBean" class="com.javarticles.spring.TestBean" autowire="byName"> <constructor-arg type="java.lang.String" value="A" /> </bean> <bean id="type1" class="com.javarticles.spring.Type1"/> <bean id="type2ByName" class="com.javarticles.spring.Type2"/> </beans>
We will explicitly register a bean of name type1ByType
so that the second time when we load the context, it is going to set both the properties.
AutowireByNameExample:
package com.javarticles.spring; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.context.support.ClassPathXmlApplicationContext; public class AutowireByNameExample { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( "autowireByNameContext.xml"); try { TestBean testBean = (TestBean) context.getBean("testBean"); System.out.println("testBean.type1ByType: " + testBean.getType1ByType()); System.out.println("testBean.type2ByName: " + testBean.getType2ByName()); RootBeanDefinition bd = new RootBeanDefinition(Type1.class); DefaultListableBeanFactory lbf = (DefaultListableBeanFactory) context.getBeanFactory(); DefaultListableBeanFactory parentLbf = new DefaultListableBeanFactory(); System.out.println("Register new bean type1ByType"); parentLbf.registerBeanDefinition("type1ByType", bd); lbf.setParentBeanFactory(parentLbf); lbf.destroySingleton("testBean"); System.out.println("Get testBean"); testBean = (TestBean) context.getBean("testBean"); System.out.println("testBean.type1ByType: " + testBean.getType1ByType()); } finally { context.close(); } } }
Output:
testBean.type1ByType: null testBean.type2ByName: Type2 Register new bean type1ByType Get testBean testBean.type1ByType: Type1
Auto-Wiring By Constructor
Just like ByType
auto-wiring, spring manages to find the beans for type1
and type2
parameters and set them.
public TestBean(Type1 type1, Type2 type2) { type1ByType = type1; type2ByName = type2; }
autowireConstructorContext.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="testBean" class="com.javarticles.spring.TestBean" autowire="constructor"> <property name="value" value="A" /> </bean> <bean id="type1" class="com.javarticles.spring.Type1"/> <bean id="type2ByName" class="com.javarticles.spring.Type2"/> </beans>
AutowireConstructorExample:
package com.javarticles.spring; import org.springframework.context.support.ClassPathXmlApplicationContext; public class AutowireConstructorExample { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( "autowireConstructorContext.xml"); try { TestBean testBean = (TestBean) context.getBean("testBean"); System.out.println("testBean.type1's value: " + testBean.getType1ByType()); System.out.println("testBean.type2's value: " + testBean.getType2ByName()); } finally { context.close(); } } }
Output:
testBean.type1's value: Type1 testBean.type2's value: Type2
Default Auto-wiring
The default-autowire
attribute is set to byName
so the strategy applies on both testBean1
and testBean2
.
defaultAutowireContext.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" default-autowire="byName"> <bean id="testBean1" class="com.javarticles.spring.TestBean"> <constructor-arg type="java.lang.String" value="A" /> </bean> <bean id="testBean2" class="com.javarticles.spring.TestBean"> <constructor-arg type="java.lang.String" value="B" /> </bean> <bean id="type1ByType" class="com.javarticles.spring.Type1"/> <bean id="type2ByName" class="com.javarticles.spring.Type2"/> </beans>
DefaultAutowireExample:
package com.javarticles.spring; import org.springframework.context.support.ClassPathXmlApplicationContext; public class DefaultAutowireExample { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( "defaultAutowireContext.xml"); try { TestBean testBean1 = (TestBean) context.getBean("testBean1"); System.out.println("testBean1.type1's value: " + testBean1.getType1ByType()); System.out.println("testBean1.type2's value: " + testBean1.getType2ByName()); TestBean testBean2 = (TestBean) context.getBean("testBean2"); System.out.println("testBean2.type1's value: " + testBean2.getType1ByType()); System.out.println("testBean2.type2's value: " + testBean2.getType2ByName()); } finally { context.close(); } } }
Output:
testBean1.type1's value: Type1 testBean1.type2's value: Type2 testBean2.type1's value: Type1 testBean2.type2's value: Type2
Override default Auto-Wiring to ‘No’
One can override default-autowire
attribute using autowire
attribute at bean
level. We set the value to no
.
noAutoWiringContxt.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" default-autowire="byType"> <bean id="testBean" class="com.javarticles.spring.TestBean" autowire="no"> <constructor-arg type="java.lang.String" value="A" /> </bean> <bean id="type1" class="com.javarticles.spring.Type1"/> <bean id="type2ByName" class="com.javarticles.spring.Type2"/> </beans>
NoAutowireExample:
package com.javarticles.spring; import org.springframework.context.support.ClassPathXmlApplicationContext; public class NoAutowireExample { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( "noAutowireContext.xml"); try { TestBean testBean = (TestBean) context.getBean("testBean"); System.out.println("testBean.type1's value: " + testBean.getType1ByType()); System.out.println("testBean.type2's value: " + testBean.getType2ByName()); } finally { context.close(); } } }
Output:
testBean.type1's value: null testBean.type2's value: null
Download the source code
This was an example about spring’s auto-wiring attributes. I showed you different strategies of auto-wiring. You can download the source code here: springAutowireExample.zip