在检索bean时,扩展groovy类会导致运行时异常

时间:2012-12-17 23:13:56

标签: spring groovy

我在尝试扩展groovy类时遇到了问题。我通过构造文件路径,使用Spring的BeanDefinitionRegistry注册bean,然后从应用程序上下文中检索它,扩展了一个从spring应用程序上下文文件加载的groovy类。

private BeanDefinitionRegistry registry;

...

    GenericBeanDefinition bd = new GenericBeanDefinition();
    bd.setBeanClass(GroovyScriptFactory.class);
    bd.setAttribute(
            ScriptFactoryPostProcessor.REFRESH_CHECK_DELAY_ATTRIBUTE,
            refreshDelay);

    ConstructorArgumentValues cav = bd.getConstructorArgumentValues();
    cav.addGenericArgumentValue(groovyLocation + WordUtils.capitalize(name)
            + ".groovy");

    registry.registerBeanDefinition(name, bd);

...

        // retrieve it
        ExternalObject engine = (ExternalObject) this.applicationContext
                .getBean(engineName);

这似乎没问题,除非我像这样扩展一个groovy类:

Cat.groovy:

package com.mycomp.external.engine;

import com.mycomp.external.ExternalObject;

    public class Cat extends ExternalObject {

    }

Lion.groovy

package com.mycomp.external.engine;

    public class Lion extends Cat {

    }

然后我发现了一个非常糟糕的错误:

Lion: 4: unable to resolve class Cat 
 @ line 4, column 1.
   public class Lion extends Cat {
   ^

1 error

    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:452) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1075) [spring-context-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at com.mycomp.external.ExternalAdFactoryImpl.getEngineByName(ExternalAdFactoryImpl.java:119) [adverter-1.9.0-SNAPSHOT.jar:na]
    at com.mycomp.external.BasicEngineTest.getEngine(BasicEngineTest.java:62) [test-classes/:na]
    at com.mycomp.external.BasicEngineTest.realModeGet(BasicEngineTest.java:108) [test-classes/:na]
    at com.mycomp.external.BasicEngineTest.testMany(BasicEngineTest.java:123) [test-classes/:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [na:1.6.0_37]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) [na:1.6.0_37]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) [na:1.6.0_37]
    at java.lang.reflect.Method.invoke(Method.java:597) [na:1.6.0_37]
    at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:76) [testng-6.0.1.jar:na]
    at org.testng.internal.MethodInvocationHelper$1.runTestMethod(MethodInvocationHelper.java:178) [testng-6.0.1.jar:na]
    at org.springframework.test.context.testng.AbstractTestNGSpringContextTests.run(AbstractTestNGSpringContextTests.java:158) [spring-test-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [na:1.6.0_37]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) [na:1.6.0_37]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) [na:1.6.0_37]
    at java.lang.reflect.Method.invoke(Method.java:597) [na:1.6.0_37]
    at org.testng.internal.MethodInvocationHelper.invokeHookable(MethodInvocationHelper.java:191) [testng-6.0.1.jar:na]
    at org.testng.internal.Invoker.invokeMethod(Invoker.java:666) [testng-6.0.1.jar:na]
    at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:846) [testng-6.0.1.jar:na]
    at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1170) [testng-6.0.1.jar:na]
    at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:125) [testng-6.0.1.jar:na]
    at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:109) [testng-6.0.1.jar:na]
    at org.testng.TestRunner.runWorkers(TestRunner.java:1147) [testng-6.0.1.jar:na]
    at org.testng.TestRunner.privateRun(TestRunner.java:749) [testng-6.0.1.jar:na]
    at org.testng.TestRunner.run(TestRunner.java:600) [testng-6.0.1.jar:na]
    at org.testng.SuiteRunner.runTest(SuiteRunner.java:317) [testng-6.0.1.jar:na]
    at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:312) [testng-6.0.1.jar:na]
    at org.testng.SuiteRunner.privateRun(SuiteRunner.java:274) [testng-6.0.1.jar:na]
    at org.testng.SuiteRunner.run(SuiteRunner.java:223) [testng-6.0.1.jar:na]
    at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52) [testng-6.0.1.jar:na]
    at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86) [testng-6.0.1.jar:na]
    at org.testng.TestNG.runSuitesSequentially(TestNG.java:1039) [testng-6.0.1.jar:na]
    at org.testng.TestNG.runSuitesLocally(TestNG.java:964) [testng-6.0.1.jar:na]
    at org.testng.TestNG.run(TestNG.java:900) [testng-6.0.1.jar:na]
    at org.apache.maven.surefire.testng.TestNGExecutor.run(TestNGExecutor.java:70) [surefire-testng-2.8.1.jar:2.8.1]
    at org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.execute(TestNGDirectoryTestSuite.java:102) [surefire-testng-2.8.1.jar:2.8.1]
    at org.apache.maven.surefire.testng.TestNGProvider.invoke(TestNGProvider.java:114) [surefire-testng-2.8.1.jar:2.8.1]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [na:1.6.0_37]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) [na:1.6.0_37]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) [na:1.6.0_37]
    at java.lang.reflect.Method.invoke(Method.java:597) [na:1.6.0_37]
    at org.apache.maven.surefire.booter.ProviderFactory$ClassLoaderProxy.invoke(ProviderFactory.java:103) [surefire-booter-2.8.1.jar:2.8.1]
    at $Proxy0.invoke(Unknown Source) [na:na]
    at org.apache.maven.surefire.booter.SurefireStarter.invokeProvider(SurefireStarter.java:150) [surefire-booter-2.8.1.jar:2.8.1]
    at org.apache.maven.surefire.booter.SurefireStarter.runSuitesInProcess(SurefireStarter.java:91) [surefire-booter-2.8.1.jar:2.8.1]
    at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:69) [surefire-booter-2.8.1.jar:2.8.1]
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'Lion': Could not determine scripted object type for GroovyScriptFactory: script source locator [file:///Users/jkramer/source/backend/backend/config/../feeds/src/main/groovy/com/mycomp/external/engine/Lion.groovy]; nested exception is org.springframework.scripting.ScriptCompilationException: Could not compile script; nested exception is org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
Lion: 4: unable to resolve class Cat 
 @ line 4, column 1.
   public class Lion extends Cat {
   ^

1 error

    at org.springframework.scripting.support.ScriptFactoryPostProcessor.postProcessBeforeInstantiation(ScriptFactoryPostProcessor.java:297) [spring-context-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInstantiation(AbstractAutowireCapableBeanFactory.java:848) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.resolveBeforeInstantiation(AbstractAutowireCapableBeanFactory.java:820) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:446) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    ... 50 common frames omitted
Caused by: org.springframework.scripting.ScriptCompilationException: Could not compile script; nested exception is org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
Lion: 4: unable to resolve class Cat 
 @ line 4, column 1.
   public class Lion extends Cat {
   ^

1 error

    at org.springframework.scripting.groovy.GroovyScriptFactory.getScriptedObjectType(GroovyScriptFactory.java:217) [spring-context-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    at org.springframework.scripting.support.ScriptFactoryPostProcessor.postProcessBeforeInstantiation(ScriptFactoryPostProcessor.java:290) [spring-context-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    ... 53 common frames omitted
Caused by: org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
Lion: 4: unable to resolve class Cat 
 @ line 4, column 1.
   public class Lion extends Cat {
   ^

1 error

    at org.codehaus.groovy.control.ErrorCollector.failIfErrors(ErrorCollector.java:302) [groovy-all-1.8.0.jar:1.8.0]
    at org.codehaus.groovy.control.CompilationUnit.applyToSourceUnits(CompilationUnit.java:854) [groovy-all-1.8.0.jar:1.8.0]
    at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:544) [groovy-all-1.8.0.jar:1.8.0]
    at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:493) [groovy-all-1.8.0.jar:1.8.0]
    at groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:306) [groovy-all-1.8.0.jar:1.8.0]
    at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:287) [groovy-all-1.8.0.jar:1.8.0]
    at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:267) [groovy-all-1.8.0.jar:1.8.0]
    at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:214) [groovy-all-1.8.0.jar:1.8.0]
    at org.springframework.scripting.groovy.GroovyScriptFactory.getScriptedObjectType(GroovyScriptFactory.java:201) [spring-context-3.0.5.RELEASE.jar:3.0.5.RELEASE]
    ... 54 common frames omitted
17:26:54.942 [Hector.me.prettyprint.cassandra.connection.CassandraHostRetryService-1] INFO  m.p.c.c.CassandraHostRetryService - Not checking that 10.10.0.111(10.10.0.111):9160 is a member of the ring since there are no live hosts

任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:0)

似乎没有直接的方法将两者都包含在源路径中(除非您在cav.addGenericArgumentValue(groovyLocation + WordUtils.capitalize(name) + ".groovy")中设置的定位器在与classpath:样式定位器路径一起使用时允许多个类,我怀疑。我认为目的是让你的加载脚本自给自足。

你可以尝试将两者结合到一个.groovy类中,但是“24.3.3.Groovy beans”here的结尾似乎可以解决这个问题。

如果您可以使用与加载ExternalObject类相同的机制加载超类,我认为可能会这样做(虽然它不太可能是你想要的)。

如果你可以避免使用继承而是在你的Lion类中使用封装,那么你可能可以在你加载的类中使用groovy类加载器来处理hacky,以便拉入另一个类,但我是不可否认的是,那里有点挥手。