8

I need to look up beans via their class type. When the beans have been wrapped by a Proxy (some methods are @Transactional) - the ApplicatoinContext fails to find them. I find that if I look them up via an interface, it works but in this case I'm working with a concrete class type. I know the bean is of the type I'm looking for but the getBean() method fails.

I can debug (and fix) the problem in Spring's AbstractBeanFactory code. The issue is that it checks the type of the beanInstance against type I'm requesting but the beanInstance.getClass() is a Proxy. AbstractBeanFactory should compensate for this and compare the type to the proxy's target class.

I have a fix for this but I don't particularly want to use a patched version of Spring and I suspect there must be something I can configure to get this working, or is this really a bug?

Alex Worden
  • 3,374
  • 6
  • 34
  • 34

2 Answers2

14

There are two major ways Spring implements AOP (e.g. @Transactional support): either by using proxy interfaces or CGLIB.

With interfaces (default) if your class implements any interfaces, Spring will create a proxy implementing all that interfaces. From now on you can only work with your bean through that interfaces. Your class is deeply burried inside them.

If you enable proxying target classes instead via :

<aop:config proxy-target-class="true">

Spring will create a subclass (obvoiusly still implementing all your interfaces) instead. This will fix your problem. However remember that the returned object is not really your class but dynamically generated subclass that wraps and delegates to your original object. This shouldn't be a problem in most of the cases.

And no, of course this is not a bug but well known behaviour and no, there is no need to patch Spring.

See also

Community
  • 1
  • 1
Tomasz Nurkiewicz
  • 334,321
  • 69
  • 703
  • 674
  • Thanks for the explanation - I did find that I could retrieve my bean via an interface. I thought about using that but the problem is that I absolutely need to refer to the concrete class in my situation (the concrete class also implements another interface that I'm relying on). I came to the conclusion that I'd use the GCLIB option today to work around it. Why would anyone not want to use that? As for using proxy classes, this smells like a bug to me, not a 'feature'! – Alex Worden Jul 18 '12 at 17:54
  • @AlexWorden: if your class implements several interfaces you can fetch bean by any of them. One of the disadvantages of CGLIB is that... you have to use CGLIB (external library). Well, it's neither a bug nor a feature - Spring has to implement AOP somehow and these are the two most common features. Also CGLIB has other side-effects like creating two instances of your class instead of one. Two much for a comment – Tomasz Nurkiewicz Jul 18 '12 at 20:33
1
<context:component-scan base-package="<Your base package name goes here>" />
<aop:aspectj-autoproxy />
<aop:config proxy-target-class="true"/>

write these three lines in applicationContext.xml this worked for me.

Dangling Piyush
  • 3,658
  • 8
  • 37
  • 52