AOP problem mit der Feder unit-tests
Habe ich eine Feder web-Anwendung, die konfiguriert ist, um JDK zu Proxyfunktion für AOP. Der AOP-Anmerkungen (wie @Transactional) deklariert sind, auf die Schnittstellen, anstatt die Implementierung Klassen.
Die Anwendung selbst funktioniert gut, aber wenn ich die unit-tests, so scheint es zu sein versucht, CGLIB für die AOP-Funktionalität (anstelle von JDK-proxying). Dies bewirkt, dass die tests fehlschlagen - ich habe es angehängt, die stack-trace-unter.
Ich verstehe nicht, warum CGLIB verwendet wird, wenn ich die tests ausführen, da die Spring-Konfiguration ist weitgehend die gleiche, als wenn die Anwendung ausgeführt wird. Eine möglicherweise bedeutende Unterschied ist, dass die test-Konfiguration verwendet eine DataSourceTransactionManager statt einen JTA-Transaktions-manager. Die test-Klassen, die sich alle verlängern AbstractJUnit4SpringContextTests, könnte es sein, dass dieser Klasse ist irgendwie hard-wired zu verwenden CGLIB?
Caused by: org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class $Proxy25]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class class $Proxy25
at org.springframework.aop.framework.Cglib2AopProxy.getProxy(Cglib2AopProxy.java:213)
at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:110)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:488)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:363)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:324)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:361)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1343)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:473)
... 79 more
Caused by: java.lang.IllegalArgumentException: Cannot subclass final class class $Proxy25
at net.sf.cglib.proxy.Enhancer.generateClass(Enhancer.java:446)
at net.sf.cglib.transform.TransformingClassGenerator.generateClass(TransformingClassGenerator.java:33)
at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216)
at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:377)
at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:285)
at org.springframework.aop.framework.Cglib2AopProxy.getProxy(Cglib2AopProxy.java:201)
... 86 more
EDIT: Einer der Kommentatoren gefordert, dass ich nach der Spring-Konfiguration. Ich habe es unten in abgekürzter form (d.h. irrelevant Bohnen und XML-namespaces weggelassen).
spring-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<!-- ANNOTATION SUPPORT -->
<!-- Include basic annotation support -->
<context:annotation-config/>
<!-- CONTROLLERS -->
<!-- Controllers, force scanning -->
<context:component-scan base-package="com.onebigplanet.web.controller,com.onebigplanet.web.ws.*"/>
<!-- Post-processor for @Aspect annotated beans, which converts them into AOP advice -->
<bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator">
<property name="proxyTargetClass" value="true"/>
</bean>
<!-- An @Aspect bean that converts exceptions thrown in POJO service implementation classes to runtime exceptions -->
<bean id="permissionAdvisor" class="com.onebigplanet.web.advisor.PermissionAdvisor"/>
<bean id="businessIntelligenceAdvisor" class="com.onebigplanet.web.advisor.bi.BusinessIntelligenceAdvisor"/>
<!-- Finds the controllers and sets an interceptor on each one -->
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
<list>
<bean class="com.onebigplanet.web.interceptor.PortalInterceptor"/>
</list>
</property>
</bean>
<!-- METHOD HANDLER ADAPTER -->
<!-- Finds mapping of url through annotation on methods of Controller -->
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="cacheSeconds" value="0"/>
<property name="webBindingInitializer">
<bean class="com.onebigplanet.web.binder.WebBindingInitializer"/>
</property>
</bean>
</beans>
applicationContext-service.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<!-- Declares a bunch of bean post-processors -->
<context:annotation-config/>
<context:component-scan base-package="com.onebigplanet.service.impl,com.onebigplanet.dao.impl.mysql" annotation-config="false"/>
<!-- Property configurer -->
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="/WEB-INF/obp-service.properties" />
</bean>
<!-- Post-processor for @Aspect annotated beans, which converts them into AOP advice -->
<bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"/>
<!-- An @Aspect bean that converts exceptions thrown in service implementation classes to runtime exceptions -->
<bean id="exceptionAdvisor" class="com.onebigplanet.service.advisor.ExceptionAdvisor"/>
<bean id="cachingAdvisor" class="com.onebigplanet.service.advisor.CacheAdvisor"/>
<bean id="businessIntelligenceAffiliateAdvisor" class="com.onebigplanet.service.advisor.BusinessIntelligenceAffiliateAdvisor"/>
<!-- Writable datasource -->
<jee:jndi-lookup id="dataSource" jndi-name="java:/ObpDS"/>
<!-- ReadOnly datasource -->
<jee:jndi-lookup id="readOnlyDataSource" jndi-name="java:/ObpReadOnlyDS"/>
<!-- Map the transaction manager to allow easy lookup of a UserTransaction -->
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>
<!-- Annotation driven transaction management -->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
applicationContext-test.xml Dies ist nur enthalten, wenn das ausführen der unit-tests. Es ist Zweck ist, zu überschreiben einige der Bohnen erklärt, in den anderen config-Dateien.
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<!-- Overwrite the property configurer bean such that it reads the test properties file instead -->
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="/obp-test.properties"/>
</bean>
<!-- All DAOs should use the test datasource -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${testDataSource.driverClassName}"/>
<property name="url" value="${testDataSource.url}"/>
<property name="username" value="${testDataSource.username}"/>
<property name="password" value="${testDataSource.password}"/>
</bean>
<bean id="readOnlyDataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${testDataSource.driverClassName}"/>
<property name="url" value="${testDataSource.url}"/>
<property name="username" value="${testDataSource.username}"/>
<property name="password" value="${testDataSource.password}"/>
</bean>
<!--
Overwrite the JTA transaction manager bean defined in applicationContent-service.xml with this one because
the implementation of the former is provided by JBoss
-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<beans>
- Ich dachte, das könnte noch mehr looks, die mit "java" und "junit" - tags, so dass ich retagged. Wünschte, ich könnte helfen mit der Antwort!
- Hmm, interessant, ich betreibe ein ähnliches setup sehr ähnlich wie bei Ihnen ohne Probleme. Können Sie einige Beispiel-code (einschließlich Ihrer Kontext-xml-Dateien)? Auch haben Sie noch andere Abhängigkeiten auf cglib? Sogar so, können Sie versuchen, es zu entfernen aus dem Klassenpfad nur um zu sehen, wenn die Bohnen Draht?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Klingt wie Sie mit Bezug auf eine Implementierung der Klasse anstatt eine Schnittstelle. Es ist ein Auszug hier mit mehr Details.
Einer Feder forum-post: "Mischen JDK und CGLIB-proxies"
Einen tollen blog-post, der erklärt,vor-und Nachteile des JDK vs. CGLIB-proxies.
Hey Jean, CGLib-proxies erstellt werden, indem bilden von Unterklassen der Klasse Proxy -- man versucht, einen proxy zu einem anderen proxy, das ist nicht zulässig, da Proxys sind sich die endgültige Klassen. Daher:
Caused by: java.lang.IllegalArgumentException: Cannot subclass final class class $Proxy25
Ich weiß nicht, ob die Lösung wurde bereits weitergegeben, und ich bin auch sicher, dass die original-requester, muss eine Lösung gefunden zu haben, da es sich um eine ein Jahr alte Abfrage. Für öffentliche Interesse, aber lassen Sie mich es hier erwähnen. Der Frühling war mit CGLIB aufgrund der folgenden Erklärung.
Die Eigenschaft sollte auf false gesetzt werden, so dass die CGLIB wird nicht ausgelöst, anstatt JDK Dynamische Proxying.
Hoffe, das hilft.