Categories
Java

@Autowired and @Resource in Spring

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:

  1. create a java project in your development IDE (eclipse, netbeans, etc.)
  2. 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
  3. create the folder “conf” and insert in the classpath
  4. 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>
    
  5. 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>
    
  6. 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());
        }
    }
    
  7. 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;
        }
    
    }
    
  8. 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

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.