Spring Bean was not found after adding an interface to its statement

advertisements

Even after turning on lots of debug this one has me mystified. I have a spring bean defined like this:

@Component
public class GraphHistoryLoader {
...
}

And I an injecting it into another bean like this:

@Component
public class StartupPostProcessor {
    @Autowired
    GraphHistoryLoader historyLoader;
}

This works fine with GraphHistoryLoader being instantiated and injected into StartupPostProcessor. However, if I then add an interface to GraphHistoryLoader like this:

@Component
public class GraphHistoryLoader implements FXCommandLineAware {
...
}

I see GraphHistoryLoader being created by Spring and made available for injection, But then the injection into StartupPostProcessor fails with:

Error creating bean with name 'startupPostProcessor':
Injection of auto wired dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException:
Could not autowire field: au.com.anz.fx.process.GraphHistoryLoader
au.com.anz.fx.process.StartupPostProcessor.historyLoader

The weird thing is that I have other classes which also implement the FXCommandLineAware interface and they work just fine. Happily being injected based on their class into other beans. It's something about this particular definition and injection that is causing the failure.

Does anyone have any ideas what to look at?


I got same problem but additionally I used Spring AOP. This means that GraphHistoryLoader from your example is proxied by Spring to achieve AOP handling. Spring uses proxies in two ways. See spring docs

  • JDK dynamic proxies. It requires your bean to implement an interface. A proxy is created based on this interface that "wraps" your actual instance of the bean. Because of that you loose concrete type information and all is left is only the interface. This is the reason why spring throws BeanCreationException
  • CGLIB. I don't know the exact details how this library works but it allows you to proxy classes that do not implement any interface. It cannot proxy a final method or final class.

To switch between these two options, when enabling spring-aop, specify flag proxy-target-class in xml.

<aop:config proxy-target-class="true">
    <!-- other beans defined here... -->
</aop:config>

Or in Java Spring Config class via annotation

@EnableAspectJAutoProxy(proxyTargetClass = true)

Note that proxies are used in Spring in other modules, like transactions and caches. Then you need to set flag proxyTargetClass in corresponding place of module in subject.