Enjoying Spring Framework Tutorials?
Subscribe to Ram N Java for easy, practical Java and Spring tutorials!
Subscribe on YouTubeCan You Use @Resource with Constructor Injection?
In Spring Framework, dependency injection can be performed using fields, setter methods, or constructors. A frequent question among developers is: Can we apply the @Resource annotation directly to a constructor?
The short answer is no. If you try to use @Resource directly on a constructor, you will encounter a compilation error. Let us dive into why this happens and what alternatives you should use instead.
The Compilation Error Explained
Suppose you create an Employee class and try to inject dependencies through its constructor using @Resource:
public class Employee {
private String name;
private Address address;
// Disallowed! Causes compile-time error
@Resource
public Employee(Address address) {
this.address = address;
}
}
The Java compiler will fail with an error stating:
"The annotation @Resource is disallowed for this location."
Why Does This Happen?
The @Resource annotation belongs to the Java standard library (javax.annotation.Resource / jakarta.annotation.Resource). If you examine the annotation definition, its target types are restricted to:
- TYPE: Classes and interfaces
- FIELD: Class properties/fields
- METHOD: Setter and regular methods
Notice that CONSTRUCTOR is completely missing from its @Target list. Because of this definition, Java does not permit the annotation on constructors.
Recommended Solutions
If you need constructor injection in Spring, use @Autowired instead:
@Autowired
public Employee(Address address) {
this.address = address;
}
If you specifically want to use @Resource, place it over the field or over the setter method rather than the constructor.
Related Spring Tutorials to Watch Next
Click here to watch on Youtube:
https://www.youtube.com/watch?v=5qNR7AZmfIo&list=UUhwKlOVR041tngjerWxVccw
Click the below Image to Enlarge:
| Apply @Resource Annotation in constructor in Spring Autowiring | Spring - @Resource annotation |
pom.xml
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0%20http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.ram.core</groupId>
<artifactId>SpringDemo</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>SpringDemo</name>
<url>http://maven.apache.org</url>
<properties>
<spring.version>5.0.2.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<!-- Spring 5 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>
</dependencies>
</project>
Address.java
public class Address
{
private String city;
private String state;
private String country;
public Address(String city, String state, String country)
{
this.city = city;
this.state = state;
this.country = country;
}
@Override
public String toString()
{
return "Address [city=" + city + ", state=" + state + ", country="
+ country + "]";
}
}
Employee.java
import javax.annotation.Resource;
public class Employee
{
private String name;
private Address address;
@Resource
public Employee(String name, Address address)
{
System.out.println("Employee(String name, Address address) constructor "
+ "is called by the Spring container");
this.name = name;
this.address = address;
}
public void displayEmployeeDetails()
{
System.out.println(
"Employee [name=" + name + ", address=" + address + "]");
}
}
applicationContext.xml
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-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<context:annotation-config />
<bean id="address" class="com.ram.model.Address">
<constructor-arg value="Chennai"></constructor-arg>
<constructor-arg value="Tamil Nadu"></constructor-arg>
<constructor-arg value="India"></constructor-arg>
</bean>
<bean id="employee" class="com.ram.model.Employee">
<constructor-arg value="Peter"></constructor-arg>
</bean>
</beans>
App.java
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.ram.model.Employee;
public class App
{
public static void main(String[] args)
{
ApplicationContext context = new ClassPathXmlApplicationContext(
"applicationContext.xml");
System.out.println("---------------------------------------");
Employee employee = (Employee) context.getBean("employee");
System.out.println(
"Got employee object from the ApplicationContext[Spring Container]");
employee.displayEmployeeDetails();
}
}
Output
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@5a2e4553: startup date [Thu Aug 23 09:23:02 IST 2018]; root of context hierarchy
Aug 23, 2018 9:23:02 AM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [applicationContext.xml]
Aug 23, 2018 9:23:03 AM org.springframework.context.support.AbstractApplicationContext refresh
WARNING: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'employee' defined in class path resource [applicationContext.xml]: Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.ram.model.Employee]: Constructor threw exception; nested exception is java.lang.Error: Unresolved compilation problem:
The annotation @Resource is disallowed for this location
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'employee' defined in class path resource [applicationContext.xml]: Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.ram.model.Employee]: Constructor threw exception; nested exception is java.lang.Error: Unresolved compilation problem:
The annotation @Resource is disallowed for this location
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:278)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1270)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1127)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:502)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:312)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:310)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:758)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:868)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:144)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:85)
at com.ram.core.App.main(App.java:12)
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.ram.model.Employee]: Constructor threw exception; nested exception is java.lang.Error: Unresolved compilation problem:
The annotation @Resource is disallowed for this location
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:175)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:117)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:271)
... 14 more
Caused by: java.lang.Error: Unresolved compilation problem:
The annotation @Resource is disallowed for this location
at com.ram.model.Employee.<init>(Employee.java:10)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:163)
... 16 more
Click the below link to download the code:
https://sites.google.com/site/ramj2eev2/java_basics/SpringDemo_Resource_annotation_cons.zip?attredirects=0&d=1
Github Link:
https://github.com/ramram43210/javaee/tree/master/Spring_2018/SpringDemo_Resource_annotation_cons
Bitbucket Link:
https://bitbucket.org/ramram43210/spring/src/02e04aa1b68a77d4f5a01ebf111e80370bd99ca8/Spring_2018/SpringDemo_Resource_annotation_cons/?at=master
See also:
No comments:
Post a Comment