16

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.

Tarlog
  • 10,024
  • 2
  • 43
  • 67
Chaitanya
  • 2,396
  • 4
  • 29
  • 45

6 Answers6

14

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.

Tarlog
  • 10,024
  • 2
  • 43
  • 67
  • This means that I have to avoid interface usage in autowired classes? – Tobia Jun 01 '16 at 14:52
  • No, no. You can autowire interface. – Tarlog Jun 02 '16 at 07:41
  • In my case I autowired with annotation and one serve was autowired by its inferface instead of its class and I had to remove the interface or create a dummy one. – Tobia Jun 02 '16 at 07:43
  • 1
    Btw, the good practice is not to use autowire at all. It slows up the bean's creation and as a result application's start-up. It's much better to use @Resource and wire by bean's name (not by type!) – Tarlog Jun 02 '16 at 08:12
  • Wonderful :-) few years ago many sw architects said to me: use autowires! What is your suggestions to like beans? – Tobia Jun 02 '16 at 08:13
  • 1
    Well, there are different architects and different opinions. Some say that most beans are singletons, thus it affects only the startup of an application, thus it's unimportant. But as a developer, it might be annoying if your application starts in two minutes instead of 30 seconds. I'm talking about quite big applications. – Tarlog Jun 02 '16 at 08:38
  • However, sometimes you have a collection of elements that let's say extend some interface and you want to wire all possible beans that implement this interface. In this case Autowiring is your only choice. – Tarlog Jun 02 '16 at 08:39
6

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)

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
3

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" />
Chaitanya
  • 2,396
  • 4
  • 29
  • 45
1

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

matsev
  • 32,104
  • 16
  • 121
  • 156
0

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 {
...
}
Raphoq
  • 99
  • 7
0

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

teobais
  • 2,820
  • 1
  • 24
  • 36