2011-10-23 1 views
7

Mam aplikacji sprężyny i robię moją klasę testową następująco:Dlaczego muszę cglib (Spring AOP), aby mieć wiele klas testowych?

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = { "classpath:/META-INF/spring/applicationContext.xml" }) 
@TransactionConfiguration(defaultRollback = true) 
@Transactional 
public class MyTest { 

} 

Kiedy próbuję utworzyć inną klasę testową i próbował uruchomić aplikację, pojawia się następujący wyjątek na nowy test klasa:

ERROR [main] (TestContextManager.java:324) - Caught exception while allowing TestExecutionListener [org.springframework.test.context.support.DependencyInjectionTestExecut 
[email protected]] to prepare test instance [[email protected]] 
org.springframework.aop.framework.AopConfigException: Cannot proxy target class because CGLIB2 is not available. Add CGLIB to the class path or specify proxy interfaces. 
     at org.springframework.aop.framework.DefaultAopProxyFactory.createAopProxy(DefaultAopProxyFactory.java:67) 
     at org.springframework.aop.framework.ProxyCreatorSupport.createAopProxy(ProxyCreatorSupport.java:104) 
     at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:112) 
     at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:476) 
     at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:362) 
     at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:322) 
     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java 
     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1426) 
     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:386) 
     at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:111) 
     at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75) 
     at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:321) 
     at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:220) 
     at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:301) 
     at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) 
     at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:303) 
     at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:240) 
     at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) 
     at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193) 
     at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52) 
     at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191) 
     at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42) 
     at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184) 
     at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) 
     at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) 
     at org.junit.runners.ParentRunner.run(ParentRunner.java:236) 
     at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:180) 
     at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:62) 
     at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.executeTestSet(AbstractDirectoryTestSuite.java:140) 
     at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.execute(AbstractDirectoryTestSuite.java:127) 
     at org.apache.maven.surefire.Surefire.run(Surefire.java:177) 
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
     at java.lang.reflect.Method.invoke(Method.java:597) 
     at org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:345) 
     at org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:1009) 

wyjątek ten został rozwiązany przez dodanie cglib do mojego ścieżki klasy, ale chcę, aby zrozumieć, dlaczego wielu klas testowych potrzebuje cglib?

Proszę o poradę, dziękuję.

+0

Czy twój "inny test" używa tego samego pliku 'applicationContext.xml'? – axtavt

+0

tak, ponieważ potrzebuję obu testów do korzystania z tej samej konfiguracji bazy danych, która istnieje w pliku applicationContext.xml. –

Odpowiedz

10

Wiosna wymaga słoiki CGLIB ponieważ używa CGLIB do proxy twoich ziaren. Dzieje się tak, jeśli skonfigurujesz sprężynę, aby użyć tego mechanizmu w swoim pliku applicationContext.xml lub jeśli Spring potrzebuje proxy dla klasy, która nie implementuje żadnych interfejsów. Dokumentacja wiosna to here i zapewnia bardzo jasne eksplantacji.

Aby korzystać z dynamicznych serwerów proxy JDK, upewnij się, że dowolne klasy proxy implementują odpowiedni interfejs i nie zmuszaj Spring do używania CGLIB przez konfigurację.

+1

Potrzeba CGLIB "jeśli Spring potrzebuje proxy dla klasy, która nie implementuje żadnych interfejsów" była dla mnie nowością. Dzięki! – Snekse

1

Domyślam się, że wiosna dodaje swoje do klasy w czasie wykonywania, a to dlatego, że potrzebne biblioteki cglib (jest on używany do manipulacji kodu bajtowego i iniekcji kodu, zobacz here)

0

Wiosna z pewnością użyje mechanizmu proxy dla niektórych twoich zajęć.

Jednak od wersji Spring 3.2 CGLIB sources are repackaged i domyślnie dodany do sprężyny rdzeniowej, więc nie trzeba ręcznie dodawać biblioteki CGLIB do ścieżki klas.

Przy okazji, jako stan spring blog entry Michael Isvy i this issue report, projekt CGLIB nie jest już aktywny. W przyszłych wersjach Spring będzie domyślnie używać Javassist.