Reputation:
I have an Bean configured in my dispatcher-servlet.xml. In a class i can successfully inject this bean with the autowired annotation e.g.
class test {
@Autowired
TestBean testBean;
}
But as soon i add an interface with the "implements" keyword to the testbean, i get an IllegalArgumentException:
java.lang.IllegalArgumentException: Can not set com.test.TestBean field com.test.myclass.testBean to com.sun.proxy.$Proxy26.
When in remove the "implements" keyword, including the name of the interface, all works fine again.
Upvotes: 1
Views: 1758
Reputation: 418
in XML:
<bean id="test" class="your.package.Test"/>
make sure Test is in your spring bean XML, you then can do
@Autowired
Test test;
test.testBean.doAnything();
thing to notice here is that you HAVE to intatiate your Test class.
Upvotes: 0
Reputation: 280168
You would need to provide more details, like the interface type and your context configuration, but the reason is the following. Spring, by default, uses JDK proxies to add AOP or decorator behavior, for example, for @Transactional
or @Async
.
JDK proxies only work with interface types, not with class types. Take this example
public class Driver {
public static void main(String[] args) throws Exception {
final Example example = new Example();
Proxied proxy = (Proxied) Proxy.newProxyInstance(Driver.class.getClassLoader(), example.getClass().getInterfaces(), new InvocationHandler() {
Example target = example;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("intercepted");
return method.invoke(example, args);
}
});
proxy.execute();
System.out.println(proxy.getClass());
System.out.println(proxy.getClass().getSuperclass());
System.out.println(Arrays.toString(proxy.getClass().getInterfaces()));
}
static class Example implements Proxied {
@Override
public void execute() {
System.out.println("Example executing.");
}
}
static interface Proxied {
void execute();
}
}
which prints
intercepted
Example executing.
class com.spring.$Proxy0
class java.lang.reflect.Proxy
[interface com.spring.Driver$Proxied]
For the purpose of this example, Spring will take the Example
bean (declared in a context), decide that it needs to proxy it, use the Example
class' interfaces, and create whatever InvocationHandler
it needs by referring to the bean as the target to invoke the method on.
What you need to take note of is that the object that is returned by Proxy.newProxyInstance(..)
is not of type Example
. It is of type Proxy
and of whatever type the interfaces of Example
are. That is why Spring cannot use the proxy object to set a field (through reflection) of type Example
, or TestBean
in your case.
Two ways to make it work. First, extract an interface from your class, if it doesn't have one already and use a field of the interface type.
Second, you can instead configure your context to use CGLIB proxies which can proxy by class type.
Upvotes: 1