使用SpEL的@CacheEvict注释在Eclipse编译之后工作,但在Ant编译之后不能工作

时间:2013-05-26 21:07:47

标签: eclipse spring ant

问题

我有一个使用Spring @CacheEvict注释和嵌入式Spring Expression语言的类。当我允许Eclipse自动编译这个类时,一切正常。但是,当我使用Ant任务(通过Eclipse或命令行)进行编译时,生成的.class文件不起作用,并抛出一个看起来像红色鲱鱼的异常。

我的问题:我如何配置Ant构建,以便生成工作.class工件(以便其他开发人员可以构建我的项目而无需Eclipse)? Eclipse和Ant之间的配置看起来是一样的,但我必须在某个地方遗漏某些属性。

版本

  • Ant(与Eclipse捆绑在一起):org.apache.ant_1.8.3.v20120321-1730
  • Eclipse:Juno Service Release 1,20120920-0800
  • JDK:1.7.0_17
  • JUnit:4.10(在项目的/ lib /中)
  • 操作系统:Windows 7 64位
  • 春天:3.2.2

支持文件

因为如果没有项目在你面前很难描述问题,我已经将我的项目归结为重现问题所需的最小文件:

/src/sample/SampleAction.java :包含使用@CacheEvict注释和SpEL的方法。

package sample;
import org.springframework.cache.annotation.CacheEvict;

public class SampleAction {
    @CacheEvict(value = "sampleCache", allEntries = true, condition = "#string.bytes != null")
    public void triggerCache(String string) {
        System.out.println("triggerCache(" + string + ")");
    }
}

/src/sample/SampleActionTest.java :一个单元测试,它与Eclipse工件一起使用,但在使用Ant工件时失败。

package sample;
import org.junit.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"application.xml"})
public class SampleActionTest {
    @Autowired
    private SampleAction sampleAction;

    @Test
    public void testCacheMethod() {
        sampleAction.triggerCache("Definitely not a null string.");
    }
}

/src/sample/application.xml :缓存和操作类的Spring定义文件。

<cache:annotation-driven />
<bean id="sampleAction" class="sample.SampleAction" />
<bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
    <property name="caches">
        <set>
            <bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" p:name="sampleCache" />
        </set>
    </property>
</bean>

/.settings/org.eclipse.jdt.core.prefs :Eclipse编译器设置(1.6到1.7.0_17):

eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.6

/build.xml :Ant构建,用于清理,编译和运行失败的单元测试。

<path id="classpath.main">
    <fileset dir="lib" includes="*.jar" />
</path>
<path id="classpath.test">
    <path refid="classpath.main" />
    <pathelement location="output/classes" />
</path>

<target name="compileFailure" description="Cleans, compiles, and runs a unit test, which fails.">
    <delete quiet="true" dir="output/classes" />
    <mkdir dir="output/classes" />      
    <copy tofile="output/classes/sample/application.xml" file="src/sample/application.xml" />
    <javac srcdir="src" destdir="output/classes"
        classpathref="classpath.main" source="1.6" target="1.6" includeantruntime="false" />
    <junit printsummary="yes">
        <classpath refid="classpath.test" />
        <formatter type="plain" usefile="false"/>
        <test name="sample.SampleActionTest" outfile="result" />
    </junit>
</target>

/ lib / * .jar :支持图书馆:

com.springsource.org.aopalliance-1.0.0.jar
commons-logging-1.1.3.jar
junit-4.10.jar
spring-aop-3.2.2.jar
spring-beans-3.2.2.jar
spring-context-3.2.2.jar
spring-context-support-3.2.2.jar
spring-core-3.2.2.jar
spring-expression-3.2.2.jar
spring-test-3.2.2.jar

此存根项目也可用作ZIP存档,包括支持Spring和JUnit的JAR文件: Minimal Eclipse Project

重现步骤

  1. 在Eclipse中打开“compilerDebug”项目。
  2. 允许Eclipse自动在“sample”包中构建类。执行项目清理/构建或打开Java文件,编辑空白,然后重新保存它们。使用Eclipse编译时,output / classes / sample / SampleAction.class为911字节。
  3. 右键单击“SampleActionTest”并选择“Run As ... JUnit Test”。 测试成功通过。
  4. 在Ant视图中打开build.xml文件。右键单击“compileFailure”目标并选择“Run As ... Ant Build”。使用“EL1007E:测试失败:在空”堆栈跟踪中找不到字段或属性'字节'。使用Ant编译时,output / classes / sample / SampleAction.class为694字节。
  5. 其他观察

    1. 我尝试将 compiler =“org.eclipse.jdt.core.JDTCompilerAdapter”添加到“javac”任务中,以强制Ant使用Eclipse编译器,但单元测试仍然在此更改后失败。 SampleAction.class在这里是696字节。
    2. 如果我从@CacheEvict注释中删除条件,则单元测试将同时通过两个编译器。
    3. 将源/目标级别设置为1.5或1.7无效。
    4. 强制Ant任务“在与工作空间相同的JRE中运行”无效。
    5. 下载独立的Ant发行版(1.9.1)并运行与Eclipse完全隔离的Ant版本无效。
    6. 使用声明性XML配置替换@CacheEvict注释(使用aspectjtools)无效。
    7. 提前感谢您帮助防止我不可避免的精神错乱。

      更新

      见下面的答案。在使用 javac 进行编译时,Ant未明确将调试模式设置为 true 。 SpEL要求将额外的调试信息包含在类文件中,以便正确处理注释。将debug设置为true会立即纠正此问题。

      <javac debug="true" [...] />
      

1 个答案:

答案 0 :(得分:1)

似乎SpEL需要java编译器才能在类文件中设置调试信息才能工作。我启用了在maven构建中生成的调试信息后,我有一个similar problem已解决。 Eclipse编译器会自动执行此操作。