[bs-73] Anonymous classes cannot be used in @Bean definitions in .groovy scripts

* Added a test for each of the classes loaded by the SpringApplication
* If it's an anonymous class or looks like a Groovy closure we ignore it
* The CLI sample job.groovy also modified to take advantage

[Fixes #48718891]
pull/1/merge
Dave Syer 12 years ago
parent 737886e4da
commit a2d328ae3a

@ -252,7 +252,7 @@
<dependency> <dependency>
<groupId>org.codehaus.groovy</groupId> <groupId>org.codehaus.groovy</groupId>
<artifactId>groovy</artifactId> <artifactId>groovy</artifactId>
<version>2.1.2</version> <version>2.1.3</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.eclipse.jetty</groupId> <groupId>org.eclipse.jetty</groupId>

@ -14,7 +14,12 @@ class JobConfig {
@Bean @Bean
protected Tasklet tasklet() { protected Tasklet tasklet() {
return new SampleTasklet() return new Tasklet() {
@Override
RepeatStatus execute(StepContribution contribution, ChunkContext context) {
return RepeatStatus.FINISHED
}
}
} }
@Bean @Bean
@ -28,13 +33,6 @@ class JobConfig {
} }
} }
class SampleTasklet implements Tasklet {
@Override
RepeatStatus execute(StepContribution contribution, ChunkContext context) {
return RepeatStatus.FINISHED
}
}
import org.springframework.util.StringUtils import org.springframework.util.StringUtils
import groovy.util.logging.Log import groovy.util.logging.Log

@ -34,6 +34,10 @@ import org.apache.ivy.util.FileUtil;
*/ */
public class CleanCommand extends OptionParsingCommand { public class CleanCommand extends OptionParsingCommand {
private static enum Layout {
IVY, MAVEN;
}
private OptionSpec<Void> allOption; private OptionSpec<Void> allOption;
public CleanCommand() { public CleanCommand() {
@ -55,28 +59,18 @@ public class CleanCommand extends OptionParsingCommand {
@Override @Override
protected void run(OptionSet options) throws Exception { protected void run(OptionSet options) throws Exception {
clean(options, getGrapesHome(options), Layout.IVY);
String dir = System.getenv("GROOVY_HOME"); clean(options, getMavenHome(options), Layout.MAVEN);
String userdir = System.getProperty("user.home");
File home;
if (dir == null || !new File(dir).exists()) {
dir = userdir;
home = new File(dir, ".groovy");
} else {
home = new File(dir);
}
if (dir == null || !new File(dir).exists()) {
return;
} }
if (!home.exists()) { private void clean(OptionSet options, File root, Layout layout) {
if (root == null || !root.exists()) {
return; return;
} }
File grapes = new File(home, "grapes");
ArrayList<String> specs = new ArrayList<String>(options.nonOptionArguments()); ArrayList<String> specs = new ArrayList<String>(options.nonOptionArguments());
if (!specs.contains("org.springframework.bootstrap")) { if (!specs.contains("org.springframework.bootstrap") && layout == Layout.IVY) {
specs.add(0, "org.springframework.bootstrap"); specs.add(0, "org.springframework.bootstrap");
} }
for (String spec : specs) { for (String spec : specs) {
@ -86,8 +80,7 @@ public class CleanCommand extends OptionParsingCommand {
group = spec.substring(0, spec.indexOf(":")); group = spec.substring(0, spec.indexOf(":"));
module = spec.substring(spec.indexOf(":") + 1); module = spec.substring(spec.indexOf(":") + 1);
} }
File file = module == null ? new File(grapes, group) : new File(new File( File file = getModulePath(root, group, module, layout);
grapes, group), module);
if (file.exists()) { if (file.exists()) {
if (options.has(this.allOption) if (options.has(this.allOption)
|| group.equals("org.springframework.bootstrap")) { || group.equals("org.springframework.bootstrap")) {
@ -102,7 +95,52 @@ public class CleanCommand extends OptionParsingCommand {
} }
} }
} }
}
private File getModulePath(File root, String group, String module, Layout layout) {
File parent = root;
if (layout == Layout.IVY) {
parent = new File(parent, group);
} else {
for (String path : group.split("\\.")) {
parent = new File(parent, path);
}
}
if (module == null) {
return parent;
}
return new File(parent, module);
}
private File getGrapesHome(OptionSet options) {
String dir = System.getenv("GROOVY_HOME");
String userdir = System.getProperty("user.home");
File home;
if (dir == null || !new File(dir).exists()) {
dir = userdir;
home = new File(dir, ".groovy");
} else {
home = new File(dir);
}
if (dir == null || !new File(dir).exists()) {
return null;
}
File grapes = new File(home, "grapes");
return grapes;
} }
private File getMavenHome(OptionSet options) {
String dir = System.getProperty("user.home");
if (dir == null || !new File(dir).exists()) {
return null;
}
File home = new File(dir);
File grapes = new File(new File(home, ".m2"), "repository");
return grapes;
}
} }

@ -71,4 +71,4 @@ if $cygwin; then
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
fi fi
${JAVA_HOME}/bin/java -cp "$CLASSPATH" org.springframework.bootstrap.cli.SpringBootstrapCli $* ${JAVA_HOME}/bin/java ${JAVA_OPTS} -cp "$CLASSPATH" org.springframework.bootstrap.cli.SpringBootstrapCli $*

@ -116,9 +116,13 @@ class BeanDefinitionLoader {
private int load(Object source) { private int load(Object source) {
Assert.notNull(source, "Source must not be null"); Assert.notNull(source, "Source must not be null");
if (source instanceof Class<?>) { if (source instanceof Class<?>) {
this.annotatedReader.register((Class<?>) source); Class<?> type = (Class<?>) source;
if (isComponent(type)) {
this.annotatedReader.register(type);
return 1; return 1;
} }
return 0;
}
if (source instanceof Resource) { if (source instanceof Resource) {
return this.xmlReader.loadBeanDefinitions((Resource) source); return this.xmlReader.loadBeanDefinitions((Resource) source);
@ -149,6 +153,15 @@ class BeanDefinitionLoader {
throw new IllegalArgumentException("Invalid source '" + source + "'"); throw new IllegalArgumentException("Invalid source '" + source + "'");
} }
private boolean isComponent(Class<?> type) {
// Nested anonymous classes are not eligible for registration, nor are groovy
// closures
if (type.isAnonymousClass() || type.getName().contains("$_closure")) {
return false;
}
return true;
}
/** /**
* Simple {@link TypeFilter} used to ensure that specified {@link Class} sources are * Simple {@link TypeFilter} used to ensure that specified {@link Class} sources are
* not accidentally re-added during scanning. * not accidentally re-added during scanning.

@ -297,11 +297,11 @@ public class SpringApplication {
} }
} }
if (context instanceof AbstractApplicationContext) { if (context instanceof AbstractApplicationContext && this.environment != null) {
((AbstractApplicationContext) context).setEnvironment(this.environment); ((AbstractApplicationContext) context).setEnvironment(this.environment);
} }
if (context instanceof GenericApplicationContext) { if (context instanceof GenericApplicationContext && this.resourceLoader != null) {
((GenericApplicationContext) context).setResourceLoader(this.resourceLoader); ((GenericApplicationContext) context).setResourceLoader(this.resourceLoader);
} }
} }

Loading…
Cancel
Save