问题
我有一个类,它使用Spring@CacheEvict注释和嵌入的Spring表达式语言。当我允许Eclipse自动编译这个类时,一切都很好。然而,当我使用Ant任务(通过Eclipse或从命令行(进行编译时,生成的.class文件不起作用,并抛出一个看起来像转移注意力的Exception。
我的问题:如何配置Ant构建,使其生成可工作的.class工件(这样其他开发人员就可以在不需要Eclipse的情况下构建我的项目(?Eclipse和Ant之间的配置看起来是一样的,但我一定在某个地方缺少了一些属性。
版本
- Ant(与Eclipse捆绑(:org.apache.Ant_1.8.3.v20120321-1730
- Eclipse:Juno Service Release 120120920-0800
- JDK:1.7.0_17
- JUnit:4.10(在项目的/lib/中(
- O/S: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文件:最小Eclipse项目
复制步骤
- 在Eclipse中打开"compilerDebug"项目
- 允许Eclipse在"sample"包中自动构建类。要么执行Project Clean/Build,要么打开Java文件,编辑空白并重新保存。使用Eclipse编译时,output/classes/sample/SampleAction.class为911字节
- 右键单击"SampleActionTest"并选择"Run As…JUnit Test">测试成功通过
- 在Ant视图中打开build.xml文件。右键单击"compileFailure"目标并选择"Run As…Ant Build">测试失败,"EL1007E:(pos 0(:在null"堆栈跟踪上找不到字段或属性"字节"。使用Ant编译时,output/classes/sample/SampleAction.class为694字节
其他观察结果
- 我曾尝试将compiler="org.eclipse.jdt.core.JDTCompilerAdapter">添加到"javac"任务中,以强制Ant使用eclipse编译器,但在更改后单元测试仍然失败。SampleAction.class在这里是696字节
- 如果我从@CacheEvict注释中删除条件,那么两个编译器的单元测试都通过了
- 将源/目标级别设置为1.5或1.7没有效果
- 强制Ant任务"在与工作区相同的JRE中运行"没有任何效果
- 下载一个独立的Ant发行版(1.9.1(并运行与Eclipse完全隔离的Ant构建没有任何效果
- 将@CacheEvict注释替换为声明性XML配置(使用aspectjtools(没有任何效果
提前感谢您帮助我避免了不可避免的精神错乱。
更新
请参阅下面提供的答案。Ant在使用javac编译时,没有将调试模式显式设置为true。SpEL要求在类文件中包含额外的调试信息,以便正确处理注释。将debug设置为true会立即更正此问题。
<javac debug="true" [...] />
SpEL似乎需要java编译器来设置类文件中的调试信息才能工作。在我启用了在maven构建中生成调试信息后,我也解决了类似的问题。Eclipse编译器会自动执行此操作。