Spring Autowiring class vs. interface?
Normally, both will work, you can autowire interfaces or classes.
There's probably an autoproxy generator somewhere in your context, which is wrapping your boo
bean in a generated proxy object. This proxy object will implement TheInterface
, but will not be a TheClass
. When using autoproxies, you need to program to the interface, not the implementation.
The likely candidate is transactional proxies - are you using Spring transactions, using AspectJ or @Transactional
?
Related videos on Youtube
Marcus Leon
Director Clearing Technology, Intercontinental Exchange. Develop the clearing systems that power ICE/NYSE's derivatives markets.
Updated on January 01, 2020Comments
-
Marcus Leon over 4 years
I have this Spring config:
<bean id="boo" class="com.x.TheClass"/>
The class
TheClass
implementsTheInterface
. Then I have this (hypothetical) Java code:@Autowired TheInterface x; @Autowired TheClass y;
The autowiring of
TheInterface
works but the autowiring ofTheClass
fails. Spring gives me aNoSuchBeanDefinitionException
for the class.Why can you wire the interface and not the class?
-
ptomli about 14 yearsIs there anything special about this class, like it being 'final', or having other instrumentation, like @Transactional, on it. You might be either missing an instrumentation lib, like CGLIB, or trying to create a subclass proxy on a final class.
-
-
skaffman about 14 years@Marcus: That's the problem then. If you use
@Transactional
and<tx:annotation-driven/>
, you cannot cast the bean toMyClass
, you have to use the interface. -
Spanky Quigman over 12 yearsI know this is a bit old, but to add a bit here... You don't have to use the interface, but in order to autowire the class directly, you need to modify the
<tx:annotation-driven />
configuration and addproxy-target-class="true"
(this defaults to false). This lets you auto-wire directly to the class. Note that there can be weird side effects, e.g. I had used some reflection to find the parameterized type for a generic base class. The inheritance is changed due to the proxy class, so I had to take that into account. You can still wire by interface withproxy-target-class="true"
. -
redochka about 11 years@SpankyQuigman thank you. This was useful. @Scope(proxyMode=ScopedProxyMode.TARGET_CLASS)