Chaitanya
Chaitanya

Reputation: 2444

Spring Autowiring only works with Interface

I am quite new to spring framework and came across the following issue.

I have an interface ClassA, which is implemented by classed ClassA1 and ClassA2.

I have the following bean definition added to applicationContext.xml

<bean id="class1" class="com.abc.ClassA1" />
<bean id="class2" class="com.abc.ClassA2" />

I would like to Autowire both the implementation classes as below.

@Autowired
private ClassA1 classA1;

@Autowired
private ClassA2 classA2;

The above code is throwing error as

Could not autowrite to field: com.abc.ClassA1 com.abc.SomeClass.classA1; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.abc.ClassA1]

But, if I change the autowiring to interface as below:

@Autowired
ClassA classA1;

Then ClassA1 is autowired to the variable. I am clueless on how can I autowire a variable to ClassA2.

Upvotes: 16

Views: 19957

Answers (6)

teobais
teobais

Reputation: 2966

From the little I've seen till now, it doesn't seem to be any restriction, regarding the type of class that one could mark as @Autowired.

Non related to the issue, but this article makes reference to the situation itself

Upvotes: 0

Raphoq
Raphoq

Reputation: 99

I have similar problem with Autowiring abstract service. You can use without any problem code like this:

@Autowired
@Qualifier("classA1")
private ClassA1 classA1;

@Autowired
@Qualifier("classA2")
private ClassA2 classA2;

This will be working only if you declare your bean like this

<bean id="class1" class="com.abc.ClassA1" />

Or like this

@Component("classA1")
public class ClassA1 {
...
}

Upvotes: 0

matsev
matsev

Reputation: 33789

You could use the @Qualifier annotation:

@Autowired
@Qualifier("class1")
ClassA classA1;

@Autowired
@Qualifier("class2")
ClassA classA2;

Ref: http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html#beans-autowired-annotation-qualifiers

or the @Resource annotation:

@Resource(name="class1")
ClassA classA1;

@Resource(name="class2")
ClassA classA2;

Ref: http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html#beans-resource-annotation

Upvotes: 1

Chaitanya
Chaitanya

Reputation: 2444

I tried multiple ways to fix this problem, but I got it working the following way.

@Autowired
private ClassA classA1;

@Autowired
private ClassA classA2;

In the application context, I defined the bean as below:

<bean id="classA1" class="com.abc.ClassA1" autowire="byName" />
<bean id="classA2" class="com.abc.ClassA2" autowire="byName" />

Upvotes: 3

Bozho
Bozho

Reputation: 597392

If your objects are proxied by JDK proxies, then they should be referred to by their interface. You can make proxies by concrete class using CGLIB (on the classpath) and proxy-target-class="true" in your aop configuration (in applicationContext.xml)

Upvotes: 6

Tarlog
Tarlog

Reputation: 10154

For some reason your classes are proxied by Spring. There many reasons why this can happen. For example if you use JPA, or AOP the original class is proxied.

If a class implements an interface, proxy means Dynamic Proxy. So basically a new class is created in runtime that implements the interfaces but does not inherit from the original class. Therefore the autowiring to the original class doesn't work.

Upvotes: 14

Related Questions