开发者

Spring - Classcast exception as CGLIB proxy cannot be forced

Here's the scenario that's driving me nuts.

  1. I have a class that has a lookup method - createOther()
  2. createOther should create an object of type Other. Other implements OtherInterfac开发者_开发百科e and in addition has a method doSomething that's marked @Async
  3. Since Other implements OtherInterface, Spring gives me a JDK proxy that I cant cast as Other.
  4. Spring docs suggest using <aop:config proxy-target-class="true"> - but I'm a newbie to that and using that doesnt seem to help.

Question: how do I tell Spring that I need a CGLib proxy that targets the Other class?

Code below fails with a classcastexception.

    Exception in thread "main" java.lang.ClassCastException: $Proxy4 cannot be cast to scratch.Other
at scratch.App$$EnhancerByCGLIB$$82d16307.createOther(<generated>)
at scratch.App.main(App.java:19)

App.java:

public class App {
public Other createOther() {
    throw new UnsupportedOperationException();
}

public static void main(final String[] args) {

    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("appcontext.xml");
    App app = (App) context.getBean("app");
    Other oth = app.createOther();
    oth.doSomething();
    System.out.println("Other created");
}

}

** Other.java **

public interface OtherInterface {

}

class Other implements OtherInterface {

@Async
public void doSomething() {
    System.out.println("did something");
}
}

** appcontext.xml **

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:task="http://www.springframework.org/schema/task"
xmlns:aop="http://www.springframework.org/schema/aop" 
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<aop:config proxy-target-class="true"></aop:config>
<bean name="app" class="scratch.App">
    <lookup-method bean="otherBean" name="createOther" />
</bean>

<bean name="otherBean" class="scratch.Other" scope="prototype">
</bean>
<task:executor id="workflowExecutorSvcPool" pool-size="5-50"
    queue-capacity="1000" keep-alive="60" />
<task:annotation-driven executor="workflowExecutorSvcPool" />

</beans>


Everything seems fine - this is the proper way to tell spring to use cglib proxies. In fact, the documentation states that it will by default make cglib proxies. The only requirement is to have cglib on your classpath. Make sure you have the cglib jar.


The task:annotation-driven element should support a proxy-target-class attribute of its own that would need to be set to true for cglib proxies, for example


Other oth = app.createOther();

This line is the issue. As the object returned is actually a proxy the method createOther() should return a OtherInterface which the proxy will implement.

It it trying to cast the Proxy version of the OtherInterface to the Other class and failing.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜