The @Autowired annotation is used to configure the dependency injection in Spring and is associated with a setter method, or a field or a constructor of a class.
In the case of a setter method or a field the bean used for dependency injection is chosen depending on the type.
Look the following example:
- create a java project in your development IDE (eclipse, netbeans, etc.)
- configure the project in Maven with the file 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>Autowired</groupId> <artifactId>Autowired</artifactId> <version>0.0.1-SNAPSHOT</version> <build> <sourceDirectory>src</sourceDirectory> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>2.3.2</version> <configuration> <source /> <target /> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>3.1.2.RELEASE</version> </dependency> <!-- log4j --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> </dependencies> </project>
otherwise you can use the following libraries:
- spring-context-3.1.2.RELEASE.jar
- spring-aop-3.1.2.RELEASE.jar
- aopalliance-1.0.jar
- spring-beans-3.1.2.RELEASE.jar
- spring-core-3.1.2.RELEASE.jar
- commons-logging-1.1.1.jar
- spring-expression-3.1.2.RELEASE.jar
- spring-asm-3.1.2.RELEASE.jar
- log4j-1.2.17.jar
- create the folder “conf” and insert in the classpath
- create the file conf/app-context.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" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd" default-lazy-init="true"> <context:component-scan base-package="eu.lucazanini" /> <bean id="simpleBean" class="eu.lucazanini.autowired.SimpleBean"> <property name="name"> <value>simple bean</value> </property> </bean> <bean id="simplePropertyOne" class="eu.lucazanini.autowired.SimpleProperty"> <property name="name"> <value>property one</value> </property> </bean> </beans>
- create the file conf/log4j.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE log4j:configuration PUBLIC "-//LOGGER" "log4j.dtd"> <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"> <appender name="stdout" class="org.apache.log4j.ConsoleAppender"> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d %-5p %c{1}:%L %m %n" /> <!-- ConversionPattern format specification %d inserts the date; you can specify the format (%d{yyyy-MM-dd HH:mm:ss,SSS}) %-5p inserts the priority log level, 5 characters, left justified %c{1} inserts the name of the class %L inserts the line number %m inserts the user message %n inserts the separator (for example, a new line) --> </layout> </appender> <appender name="fileAppender" class="org.apache.log4j.RollingFileAppender"> <param name="append" value="false" /> <param name="Threshold" value="DEBUG" /> <param name="File" value="logs/app.log"/> <param name="MaxFileSize" value="512KB" /> <param name="MaxBackupIndex" value="10" /> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d %-5p %c{1}:%L %m %n" /> </layout> </appender> <!--sets the priority log level for org.springframework--> <logger name="org.springframework"> <level value="info"/> </logger> <!--sets the priority log level for eu.lucazanini--> <logger name= "eu.lucazanini"> <level value="debug"/> </logger> <!--sets the default priority log level--> <root> <priority value="debug"></priority> <appender-ref ref="stdout"/> <appender-ref ref="fileAppender"/> </root> </log4j:configuration>
- create the file eu/lucazanini/autowired/Main.java
package eu.lucazanini.autowired; import org.apache.log4j.Logger; import org.springframework.context.support.*; public class Main { private static Logger log = Logger.getLogger(Main.class); public static void main(String[] args) { GenericXmlApplicationContext ctx = new GenericXmlApplicationContext(); ctx.load("classpath:app-context.xml"); ctx.refresh(); SimpleBean bean = (SimpleBean) ctx.getBean("simpleBean"); log.debug("The name is " + bean.getName()); log.debug("The name of the property is " + bean.getProperty().getName()); } }
- create the file eu/lucazanini/autowired/SimpleBean.java
package eu.lucazanini.autowired; import org.springframework.beans.factory.annotation.Autowired; public class SimpleBean { private String name; private SimpleProperty property; public String getName() { return name; } public void setName(String name) { this.name = name; } public SimpleProperty getProperty() { return property; } @Autowired public void setProperty(SimpleProperty property) { this.property = property; } }
- create the file eu/lucazanini/autowired/SimpleProperty.java
package eu.lucazanini.autowired; import org.springframework.beans.factory.annotation.Autowired; public class SimpleProperty { private String name; public String getName() { return name; } @Autowired public void setName(String name) { this.name = name; } }
In this example @Autowired is used to inject the dependency with class = “eu.lucazanini.autowired.SimpleProperty” in SimpleBean, with a bean that is an instance of the PropertyBean class which is the one used by the setter method “setProperty” in SimpleBean.
@Autowired can have the attribute “required” set to true or false:
@Autowired(required=true)
@Autowired(required=false)
The default value for “required” is true.
When Spring is not able to determine the dependency, you get an exception if you don’t set “required” to false.
Now consider the example above after replacing the file conf/app-context.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" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd" default-lazy-init="true"> <context:component-scan base-package="eu.lucazanini" /> <bean id="simpleBean" class="eu.lucazanini.autowired.SimpleBean"> <property name="name"> <value>simple bean</value> </property> </bean> <bean id="simplePropertyOne" class="eu.lucazanini.autowired.SimpleProperty"> <property name="name"> <value>property one</value> </property> </bean> <bean id="simplePropertyTwo" class="eu.lucazanini.autowired.SimpleProperty"> <property name="name"> <value>property two</value> </property> </bean> </beans>
where you added the bean simplePropertyTwo of the same class of the bean simplePropertyOne already present.
Now you get the exception:
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'simpleBean': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void eu.lucazanini.autowired.SimpleBean.setProperty(eu.lucazanini.autowired.SimpleProperty); nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [eu.lucazanini.autowired.SimpleProperty] is defined: expected single matching bean but found 2: [simplePropertyOne, simplePropertyTwo]
It is obvious that the error is due to the ambiguity in determining which instance of the class SimpleProperty must be injected as a dependency in SimpleBean (simplePropertyOne or simplePropertyTwo).
To avoid this error you can use the annotation @Qualifier specifying the id of the right bean in eu/lucazanini/autowired/SimpleBean.java
package eu.lucazanini.autowired; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; public class SimpleBean { private String name; private SimpleProperty property; public String getName() { return name; } public void setName(String name) { this.name = name; } public SimpleProperty getProperty() { return property; } @Autowired @Qualifier("simplePropertyOne") public void setProperty(SimpleProperty property) { this.property = property; } }
You can replace @Autowired and @Qualifier with @Resource and the attribute “name” as in the following example:
@Resource(name = "simplePropertyOne")
The following table is a summary of the full post:
@Autowired | @Resource |
---|---|
Spring annotation | JSR-250 |
injection by type or injection by name with @Qualifier |
injection by name |
mandatory but not with required = false | mandatory |
Leave a Reply