Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to unproxy a Spring bean?

Tags:

java

spring

I have a Spring bean, let's say:

@TransactionAttribute(TransactionAttributeType.REQUIRED)  public class AImpl implements A {       public void setSomeDependency(D dependency) {          // This setter DOES NOT BELONG to interface A      } }  <bean id="aImpl" class="AImpl"/> 

Now I want to integration test it, but first I need to mock the dependency D, because it does too much stuff. Since the AImpl implements an interface and contains a transactional annotation, the generated proxy is only compatible with the interface A, so I can do this:

@Inject @Named("aImpl") private A a; 

but cannot:

@Inject @Named("aImpl") private AImpl a; 

As a result, I can't mock my dependency.

Please note that adding void setSomeDependency(D dependency) to interface A is not an option, as it has no business meaning. Neither it is using the proxy-target-class="true", as it breaks a whole lot of other beans (this attribute affects all beans in the context).

Is there a way to unproxy the injected bean A, so I could cast it to AImpl?

like image 610
MaDa Avatar asked Nov 14 '11 12:11

MaDa


People also ask

What is bean proxy?

Proxying means that your client code thinks it's talking to one bean, but a proxy is really doing the listening and responding. This has been true since early distributed client/server computing models like CORBA.

What is proxy in Spring?

The Proxy pattern uses a proxy (surrogate) object “in place of” another object. The objective of a proxy object is to control the creation of and access to the real object it represents.

What are the two types of proxies used in Spring?

Spring used two types of proxy strategy one is JDK dynamic proxy and other one is CGLIB proxy.

Why do we need proxy in Spring?

JDK Dynamic Proxies and CGLIB. Proxies in Spring are an implementation of the Proxy design pattern and help facilitate the paradigm of Aspect-Oriented Programming. Can inject additional functionality when an object is accessed such as logging, caching, transaction management, etc.


1 Answers

Try this:

if(AopUtils.isAopProxy(a) && a instanceof Advised) {     Object target = ((Advised)a).getTargetSource().getTarget();     AImpl ai = (AImpl)target; } 

Bonus: in Scala I am using the following equivalent function for the very same purpose:

def unwrapProxy(a: AnyRef) = a match {     case advised: Advised if(AopUtils.isAopProxy(advised)) =>                              advised.getTargetSource.getTarget     case notProxy => notProxy } 
like image 196
Tomasz Nurkiewicz Avatar answered Sep 19 '22 14:09

Tomasz Nurkiewicz