Remove "Feature" support introduced in 3.1 M1
Feature-related support such as @Feature, @FeatureConfiguration, and FeatureSpecification types will be replaced by framework-provided @Configuration classes and convenience annotations such as @ComponentScan (already exists), @EnableAsync, @EnableScheduling, @EnableTransactionManagement and others. Issue: SPR-8012,SPR-8034,SPR-8039,SPR-8188,SPR-8206,SPR-8223, SPR-8225,SPR-8226,SPR-8227
This commit is contained in:
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.context.annotation;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.configuration.StubSpecification;
|
||||
import org.springframework.context.config.FeatureSpecification;
|
||||
|
||||
/**
|
||||
* Tests that @FeatureConfiguration classes may implement Aware interfaces,
|
||||
* such as BeanFactoryAware. This is not generally recommended but occasionally
|
||||
* useful, particularly in testing.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @since 3.1
|
||||
*/
|
||||
public class BeanFactoryAwareFeatureConfigurationTests {
|
||||
@Test
|
||||
public void test() {
|
||||
ConfigurableApplicationContext ctx =
|
||||
new AnnotationConfigApplicationContext(FeatureConfig.class);
|
||||
FeatureConfig fc = ctx.getBean(FeatureConfig.class);
|
||||
assertThat(fc.featureMethodWasCalled, is(true));
|
||||
assertThat(fc.gotBeanFactoryInTime, is(true));
|
||||
assertThat(fc.beanFactory, is(ctx.getBeanFactory()));
|
||||
}
|
||||
|
||||
@FeatureConfiguration
|
||||
static class FeatureConfig implements BeanFactoryAware {
|
||||
|
||||
ConfigurableListableBeanFactory beanFactory;
|
||||
boolean featureMethodWasCalled = false;
|
||||
boolean gotBeanFactoryInTime = false;
|
||||
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
this.beanFactory = (ConfigurableListableBeanFactory)beanFactory;
|
||||
}
|
||||
|
||||
@Feature
|
||||
public FeatureSpecification f() {
|
||||
this.featureMethodWasCalled = true;
|
||||
this.gotBeanFactoryInTime = (this.beanFactory != null);
|
||||
return new StubSpecification();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.context.annotation;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
|
||||
import org.springframework.beans.factory.parsing.FailFastProblemReporter;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.context.config.SpecificationContext;
|
||||
import org.springframework.core.io.DefaultResourceLoader;
|
||||
import org.springframework.mock.env.MockEnvironment;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link ComponentScanExecutor}.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @since 3.1
|
||||
*/
|
||||
public class ComponentScanExecutorTests {
|
||||
|
||||
private ComponentScanExecutor executor;
|
||||
private SpecificationContext specificationContext;
|
||||
private DefaultListableBeanFactory bf;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
this.bf = new DefaultListableBeanFactory();
|
||||
this.executor = new ComponentScanExecutor();
|
||||
this.specificationContext = new SpecificationContext();
|
||||
this.specificationContext.setRegistry(bf);
|
||||
this.specificationContext.setResourceLoader(new DefaultResourceLoader());
|
||||
this.specificationContext.setEnvironment(new MockEnvironment());
|
||||
this.specificationContext.setRegistrar(new SimpleComponentRegistrar(bf));
|
||||
this.specificationContext.setProblemReporter(new FailFastProblemReporter());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validSpec() {
|
||||
this.executor.execute(new ComponentScanSpec("example.scannable"), this.specificationContext);
|
||||
assertThat(bf.containsBean("fooServiceImpl"), is(true));
|
||||
}
|
||||
|
||||
@Test(expected=BeanDefinitionParsingException.class)
|
||||
public void invalidSpec() {
|
||||
// ff problem reporter should throw due to no packages specified
|
||||
this.executor.execute(new ComponentScanSpec(), this.specificationContext);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.context.annotation;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class ComponentScanFeatureTests {
|
||||
@Test
|
||||
public void viaContextRegistration() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(ComponentScanFeatureConfig.class);
|
||||
ctx.register(ComponentScanFeatureConfig.Features.class);
|
||||
ctx.refresh();
|
||||
ctx.getBean(ComponentScanFeatureConfig.class);
|
||||
ctx.getBean(TestBean.class);
|
||||
assertThat("config class bean not found", ctx.containsBeanDefinition("componentScanFeatureConfig"), is(true));
|
||||
assertThat("@ComponentScan annotated @Configuration class registered directly against " +
|
||||
"AnnotationConfigApplicationContext did not trigger component scanning as expected",
|
||||
ctx.containsBean("fooServiceImpl"), is(true));
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
//@Import(ComponentScanFeatureConfig.Features.class)
|
||||
class ComponentScanFeatureConfig {
|
||||
@FeatureConfiguration
|
||||
static class Features {
|
||||
@Feature
|
||||
public ComponentScanSpec componentScan() {
|
||||
return new ComponentScanSpec(example.scannable._package.class);
|
||||
}
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TestBean testBean() {
|
||||
return new TestBean();
|
||||
}
|
||||
}
|
||||
@@ -1,411 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.context.annotation;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.nullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.springframework.util.StringUtils.arrayToCommaDelimitedString;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
|
||||
import org.springframework.beans.factory.parsing.FailFastProblemReporter;
|
||||
import org.springframework.beans.factory.parsing.Problem;
|
||||
import org.springframework.beans.factory.parsing.ProblemReporter;
|
||||
import org.springframework.beans.factory.support.BeanNameGenerator;
|
||||
import org.springframework.beans.factory.support.DefaultBeanNameGenerator;
|
||||
import org.springframework.core.type.classreading.MetadataReader;
|
||||
import org.springframework.core.type.classreading.MetadataReaderFactory;
|
||||
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
||||
import org.springframework.core.type.filter.AssignableTypeFilter;
|
||||
import org.springframework.core.type.filter.TypeFilter;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link ComponentScanSpec}.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @since 3.1
|
||||
*/
|
||||
public class ComponentScanSpecTests {
|
||||
|
||||
private CollatingProblemReporter problemReporter;
|
||||
private ClassLoader classLoader;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
problemReporter = new CollatingProblemReporter();
|
||||
classLoader = ClassUtils.getDefaultClassLoader();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void includeAnnotationConfig() {
|
||||
ComponentScanSpec spec = new ComponentScanSpec("org.p1");
|
||||
assertThat(spec.includeAnnotationConfig(), nullValue());
|
||||
spec.includeAnnotationConfig(true);
|
||||
assertThat(spec.validate(problemReporter), is(true));
|
||||
assertThat(spec.includeAnnotationConfig(), is(true));
|
||||
spec.includeAnnotationConfig(false);
|
||||
assertThat(spec.validate(problemReporter), is(true));
|
||||
assertThat(spec.includeAnnotationConfig(), is(false));
|
||||
spec.includeAnnotationConfig("trUE");
|
||||
assertThat(spec.validate(problemReporter), is(true));
|
||||
assertThat(spec.includeAnnotationConfig(), is(true));
|
||||
spec.includeAnnotationConfig("falSE");
|
||||
assertThat(spec.validate(problemReporter), is(true));
|
||||
assertThat(spec.includeAnnotationConfig(), is(false));
|
||||
spec.includeAnnotationConfig("");
|
||||
assertThat(spec.validate(problemReporter), is(true));
|
||||
assertThat(spec.includeAnnotationConfig(), is(false));
|
||||
spec.includeAnnotationConfig((String)null);
|
||||
assertThat(spec.validate(problemReporter), is(true));
|
||||
assertThat(spec.includeAnnotationConfig(), is(false));
|
||||
spec.includeAnnotationConfig((Boolean)null);
|
||||
assertThat(spec.validate(problemReporter), is(true));
|
||||
assertThat(spec.includeAnnotationConfig(), nullValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resourcePattern() {
|
||||
ComponentScanSpec spec = new ComponentScanSpec("org.p1");
|
||||
assertThat(spec.resourcePattern(), nullValue());
|
||||
assertThat(spec.validate(problemReporter), is(true));
|
||||
spec.resourcePattern("**/Foo*.class");
|
||||
assertThat(spec.resourcePattern(), is("**/Foo*.class"));
|
||||
assertThat(spec.validate(problemReporter), is(true));
|
||||
spec.resourcePattern("");
|
||||
assertThat(spec.resourcePattern(), is("**/Foo*.class"));
|
||||
assertThat(spec.validate(problemReporter), is(true));
|
||||
spec.resourcePattern(null);
|
||||
assertThat(spec.resourcePattern(), is("**/Foo*.class"));
|
||||
assertThat(spec.validate(problemReporter), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void useDefaultFilters() {
|
||||
ComponentScanSpec spec = new ComponentScanSpec("org.p1");
|
||||
assertThat(spec.useDefaultFilters(), nullValue());
|
||||
assertThat(spec.validate(problemReporter), is(true));
|
||||
spec.useDefaultFilters((Boolean)null);
|
||||
assertThat(spec.useDefaultFilters(), nullValue());
|
||||
assertThat(spec.validate(problemReporter), is(true));
|
||||
spec.useDefaultFilters(true);
|
||||
assertThat(spec.useDefaultFilters(), is(true));
|
||||
assertThat(spec.validate(problemReporter), is(true));
|
||||
spec.useDefaultFilters(false);
|
||||
assertThat(spec.useDefaultFilters(), is(false));
|
||||
assertThat(spec.validate(problemReporter), is(true));
|
||||
spec.useDefaultFilters("trUE");
|
||||
assertThat(spec.useDefaultFilters(), is(true));
|
||||
assertThat(spec.validate(problemReporter), is(true));
|
||||
spec.useDefaultFilters("falSE");
|
||||
assertThat(spec.useDefaultFilters(), is(false));
|
||||
assertThat(spec.validate(problemReporter), is(true));
|
||||
spec.useDefaultFilters("");
|
||||
assertThat(spec.useDefaultFilters(), is(false));
|
||||
assertThat(spec.validate(problemReporter), is(true));
|
||||
spec.useDefaultFilters((String)null);
|
||||
assertThat(spec.useDefaultFilters(), is(false));
|
||||
assertThat(spec.validate(problemReporter), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void includeFilters() {
|
||||
ComponentScanSpec spec = new ComponentScanSpec("org.p1");
|
||||
spec.includeFilters(
|
||||
new AnnotationTypeFilter(MyAnnotation.class),
|
||||
new AssignableTypeFilter(Object.class));
|
||||
assertThat(spec.validate(problemReporter), is(true));
|
||||
assertThat(spec.includeFilters().length, is(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stringIncludeExcludeFilters() {
|
||||
ComponentScanSpec spec = new ComponentScanSpec("org.p1");
|
||||
spec.addIncludeFilter("annotation", MyAnnotation.class.getName(), classLoader);
|
||||
spec.addExcludeFilter("assignable", Object.class.getName(), classLoader);
|
||||
spec.addExcludeFilter("annotation", Override.class.getName(), classLoader);
|
||||
assertThat(spec.validate(problemReporter), is(true));
|
||||
assertThat(spec.includeFilters().length, is(1));
|
||||
assertThat(spec.excludeFilters().length, is(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bogusStringIncludeFilter() throws IOException {
|
||||
ComponentScanSpec spec = new ComponentScanSpec("org.p1");
|
||||
spec.addIncludeFilter("bogus-type", "bogus-expr", classLoader);
|
||||
assertThat(spec.validate(problemReporter), is(false));
|
||||
assertThat(spec.includeFilters().length, is(1));
|
||||
try {
|
||||
spec.includeFilters()[0].match(null, null);
|
||||
fail("expected placholder TypeFilter to throw exception");
|
||||
} catch (UnsupportedOperationException ex) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void exerciseFilterTypes() throws IOException {
|
||||
ComponentScanSpec spec = new ComponentScanSpec("org.p1");
|
||||
spec.addIncludeFilter("aspectj", "*..Bogus", classLoader);
|
||||
assertThat(spec.validate(problemReporter), is(true));
|
||||
spec.addIncludeFilter("regex", ".*Foo", classLoader);
|
||||
assertThat(spec.validate(problemReporter), is(true));
|
||||
spec.addIncludeFilter("custom", StubTypeFilter.class.getName(), classLoader);
|
||||
assertThat(spec.validate(problemReporter), is(true));
|
||||
spec.addIncludeFilter("custom", "org.NonExistentTypeFilter", classLoader);
|
||||
assertThat(spec.validate(problemReporter), is(false));
|
||||
spec.addIncludeFilter("custom", NonNoArgResolver.class.getName(), classLoader);
|
||||
assertThat(spec.validate(problemReporter), is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingBasePackages() {
|
||||
ComponentScanSpec spec = new ComponentScanSpec();
|
||||
assertThat(spec.validate(problemReporter), is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withBasePackageViaAdderMethod() {
|
||||
ComponentScanSpec spec = new ComponentScanSpec();
|
||||
spec.addBasePackage("org.p1");
|
||||
spec.addBasePackage("org.p2");
|
||||
assertThat(spec.validate(problemReporter), is(true));
|
||||
assertExactContents(spec.basePackages(), "org.p1", "org.p2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withBasePackagesViaStringConstructor() {
|
||||
ComponentScanSpec spec = new ComponentScanSpec("org.p1", "org.p2");
|
||||
assertThat(spec.validate(problemReporter), is(true));
|
||||
assertExactContents(spec.basePackages(), "org.p1", "org.p2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withBasePackagesViaClassConstructor() {
|
||||
ComponentScanSpec spec = new ComponentScanSpec(java.lang.Object.class, java.io.Closeable.class);
|
||||
assertThat(spec.validate(problemReporter), is(true));
|
||||
assertExactContents(spec.basePackages(), "java.lang", "java.io");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void forDelimitedPackages() {
|
||||
ComponentScanSpec spec = ComponentScanSpec.forDelimitedPackages("pkg.one,pkg.two");
|
||||
assertTrue(ObjectUtils.containsElement(spec.basePackages(), "pkg.one"));
|
||||
assertTrue(ObjectUtils.containsElement(spec.basePackages(), "pkg.two"));
|
||||
assertThat(spec.basePackages().length, is(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withSomeEmptyBasePackages() {
|
||||
ComponentScanSpec spec = new ComponentScanSpec("org.p1", "", "org.p3");
|
||||
assertThat(spec.validate(problemReporter), is(true));
|
||||
assertExactContents(spec.basePackages(), "org.p1", "org.p3");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withAllEmptyBasePackages() {
|
||||
ComponentScanSpec spec = new ComponentScanSpec("", "", "");
|
||||
assertThat(spec.validate(problemReporter), is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withInstanceBeanNameGenerator() {
|
||||
ComponentScanSpec spec = new ComponentScanSpec("org.p1");
|
||||
assertThat(spec.beanNameGenerator(), nullValue());
|
||||
BeanNameGenerator bng = new DefaultBeanNameGenerator();
|
||||
spec.beanNameGenerator(bng);
|
||||
assertThat(spec.validate(problemReporter), is(true));
|
||||
assertThat(spec.beanNameGenerator(), is(bng));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withStringBeanNameGenerator() {
|
||||
ComponentScanSpec spec = new ComponentScanSpec("org.p1");
|
||||
spec.beanNameGenerator(DefaultBeanNameGenerator.class.getName(), classLoader);
|
||||
assertThat(spec.validate(problemReporter), is(true));
|
||||
assertThat(spec.beanNameGenerator(), instanceOf(DefaultBeanNameGenerator.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withInstanceScopeMetadataResolver() {
|
||||
ComponentScanSpec spec = new ComponentScanSpec("org.p1");
|
||||
assertThat(spec.scopeMetadataResolver(), nullValue());
|
||||
ScopeMetadataResolver smr = new AnnotationScopeMetadataResolver();
|
||||
spec.scopeMetadataResolver(smr);
|
||||
assertThat(spec.validate(problemReporter), is(true));
|
||||
assertThat(spec.scopeMetadataResolver(), is(smr));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withStringScopeMetadataResolver() {
|
||||
ComponentScanSpec spec = new ComponentScanSpec("org.p1");
|
||||
spec.scopeMetadataResolver(AnnotationScopeMetadataResolver.class.getName(), classLoader);
|
||||
assertThat(spec.validate(problemReporter), is(true));
|
||||
assertThat(spec.scopeMetadataResolver(), instanceOf(AnnotationScopeMetadataResolver.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withNonAssignableStringScopeMetadataResolver() {
|
||||
ComponentScanSpec spec = new ComponentScanSpec("org.p1");
|
||||
spec.scopeMetadataResolver(Object.class.getName(), classLoader);
|
||||
assertThat(spec.validate(problemReporter), is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withNonExistentStringScopeMetadataResolver() {
|
||||
ComponentScanSpec spec = new ComponentScanSpec("org.p1");
|
||||
spec.scopeMetadataResolver("org.Bogus", classLoader);
|
||||
assertThat(spec.validate(problemReporter), is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withNonNoArgStringScopeMetadataResolver() {
|
||||
ComponentScanSpec spec = new ComponentScanSpec("org.p1");
|
||||
spec.scopeMetadataResolver(NonNoArgResolver.class.getName(), classLoader);
|
||||
assertThat(spec.validate(problemReporter), is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withStringScopedProxyMode() {
|
||||
ComponentScanSpec spec = new ComponentScanSpec("org.p1");
|
||||
spec.scopedProxyMode("targetCLASS");
|
||||
assertThat(spec.validate(problemReporter), is(true));
|
||||
assertThat(spec.scopedProxyMode(), is(ScopedProxyMode.TARGET_CLASS));
|
||||
spec.scopedProxyMode("interFACES");
|
||||
assertThat(spec.validate(problemReporter), is(true));
|
||||
assertThat(spec.scopedProxyMode(), is(ScopedProxyMode.INTERFACES));
|
||||
spec.scopedProxyMode("nO");
|
||||
assertThat(spec.validate(problemReporter), is(true));
|
||||
assertThat(spec.scopedProxyMode(), is(ScopedProxyMode.NO));
|
||||
spec.scopedProxyMode("bogus");
|
||||
assertThat(spec.validate(problemReporter), is(false));
|
||||
assertThat(spec.scopedProxyMode(), nullValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withScopeMetadataResolverAndScopedProxyMode() {
|
||||
ComponentScanSpec spec = new ComponentScanSpec("org.p1");
|
||||
spec.scopeMetadataResolver(new AnnotationScopeMetadataResolver());
|
||||
assertThat(spec.validate(problemReporter), is(true));
|
||||
spec.scopedProxyMode(ScopedProxyMode.INTERFACES);
|
||||
assertThat(spec.validate(problemReporter), is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addBasePackage() {
|
||||
ComponentScanSpec spec = new ComponentScanSpec();
|
||||
spec.addBasePackage("foo.bar");
|
||||
assertThat(spec.validate(problemReporter), is(true));
|
||||
assertThat(spec.basePackages().length, is(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addBasePackageWithConstructor() {
|
||||
ComponentScanSpec spec = new ComponentScanSpec("my.pkg");
|
||||
spec.addBasePackage("foo.bar");
|
||||
assertThat(spec.validate(problemReporter), is(true));
|
||||
assertThat(spec.basePackages().length, is(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addExcludeFilterString() {
|
||||
ComponentScanSpec spec = new ComponentScanSpec("my.pkg");
|
||||
spec.addExcludeFilter("annotation", MyAnnotation.class.getName(), ClassUtils.getDefaultClassLoader());
|
||||
assertThat(spec.validate(problemReporter), is(true));
|
||||
assertThat(spec.excludeFilters().length, is(1));
|
||||
assertThat(spec.excludeFilters()[0], instanceOf(AnnotationTypeFilter.class));
|
||||
}
|
||||
|
||||
@Test(expected=BeanDefinitionParsingException.class)
|
||||
public void withFailFastProblemReporter() {
|
||||
new ComponentScanSpec().validate(new FailFastProblemReporter());
|
||||
}
|
||||
|
||||
private <T> void assertExactContents(T[] actual, T... expected) {
|
||||
if (actual.length >= expected.length) {
|
||||
for (int i = 0; i < expected.length; i++) {
|
||||
assertThat(
|
||||
String.format("element number %d in actual is incorrect. actual: [%s], expected: [%s]",
|
||||
i, arrayToCommaDelimitedString(actual), arrayToCommaDelimitedString(expected)),
|
||||
actual[i], equalTo(expected[i]));
|
||||
}
|
||||
}
|
||||
assertThat(String.format("actual contains incorrect number of arguments. actual: [%s], expected: [%s]",
|
||||
arrayToCommaDelimitedString(actual), arrayToCommaDelimitedString(expected)),
|
||||
actual.length, equalTo(expected.length));
|
||||
}
|
||||
|
||||
|
||||
private static class CollatingProblemReporter implements ProblemReporter {
|
||||
|
||||
private List<Problem> errors = new ArrayList<Problem>();
|
||||
|
||||
private List<Problem> warnings = new ArrayList<Problem>();
|
||||
|
||||
|
||||
public void fatal(Problem problem) {
|
||||
throw new BeanDefinitionParsingException(problem);
|
||||
}
|
||||
|
||||
public void error(Problem problem) {
|
||||
this.errors.add(problem);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public Problem[] getErrors() {
|
||||
return this.errors.toArray(new Problem[this.errors.size()]);
|
||||
}
|
||||
|
||||
public void warning(Problem problem) {
|
||||
System.out.println(problem);
|
||||
this.warnings.add(problem);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public Problem[] getWarnings() {
|
||||
return this.warnings.toArray(new Problem[this.warnings.size()]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class NonNoArgResolver implements ScopeMetadataResolver {
|
||||
public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
private static class StubTypeFilter implements TypeFilter {
|
||||
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
|
||||
throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,312 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.context.annotation;
|
||||
|
||||
import static java.lang.String.format;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.not;
|
||||
import static org.hamcrest.CoreMatchers.sameInstance;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.springframework.context.annotation.EarlyBeanReferenceProxyCreator.MISSING_NO_ARG_CONSTRUCTOR_ERROR_MESSAGE;
|
||||
import static org.springframework.context.annotation.EarlyBeanReferenceProxyCreator.PRIVATE_NO_ARG_CONSTRUCTOR_ERROR_MESSAGE;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.config.DependencyDescriptor;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.core.MethodParameter;
|
||||
|
||||
import test.beans.ITestBean;
|
||||
import test.beans.TestBean;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link EarlyBeanReferenceProxyCreator}, ensuring that
|
||||
* {@link EarlyBeanReferenceProxy} objects behave properly.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @since 3.1
|
||||
*/
|
||||
public class EarlyBeanReferenceProxyCreatorTests {
|
||||
|
||||
private DefaultListableBeanFactory bf;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
bf = new DefaultListableBeanFactory();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void proxyToStringAvoidsEagerInstantiation() throws Exception {
|
||||
EarlyBeanReferenceProxyCreator pc = new EarlyBeanReferenceProxyCreator(bf);
|
||||
|
||||
TestBean proxy = (TestBean) pc.createProxyIfPossible(descriptorFor(TestBean.class));
|
||||
|
||||
assertThat(proxy.toString(), equalTo("EarlyBeanReferenceProxy for bean of type TestBean"));
|
||||
}
|
||||
|
||||
@Test(expected=NoSuchBeanDefinitionException.class)
|
||||
public void proxyThrowsNoSuchBeanDefinitionExceptionWhenDelegatingMethodCallToNonExistentBean() throws Exception {
|
||||
EarlyBeanReferenceProxyCreator pc = new EarlyBeanReferenceProxyCreator(bf);
|
||||
TestBean proxy = (TestBean) pc.createProxyIfPossible(descriptorFor(TestBean.class));
|
||||
|
||||
proxy.getName();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void proxyHashCodeAvoidsEagerInstantiation() throws Exception {
|
||||
EarlyBeanReferenceProxyCreator pc = new EarlyBeanReferenceProxyCreator(bf);
|
||||
TestBean proxy = (TestBean) pc.createProxyIfPossible(descriptorFor(TestBean.class));
|
||||
|
||||
assertThat(proxy.hashCode(), equalTo(System.identityHashCode(proxy)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void proxyEqualsAvoidsEagerInstantiation() throws Exception {
|
||||
EarlyBeanReferenceProxyCreator pc = new EarlyBeanReferenceProxyCreator(bf);
|
||||
|
||||
TestBean proxy = (TestBean) pc.createProxyIfPossible(descriptorFor(TestBean.class));
|
||||
|
||||
assertThat(proxy.equals(new Object()), is(false));
|
||||
assertThat(proxy.equals(proxy), is(true));
|
||||
|
||||
TestBean proxy2 = (TestBean) pc.createProxyIfPossible(descriptorFor(TestBean.class));
|
||||
|
||||
assertThat(proxy, not(sameInstance(proxy2)));
|
||||
assertThat(proxy.equals(proxy2), is(false));
|
||||
assertThat(proxy2.equals(proxy), is(false));
|
||||
assertThat(proxy2.equals(proxy2), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void proxyFinalizeAvoidsEagerInstantiation() throws Exception {
|
||||
EarlyBeanReferenceProxyCreator pc = new EarlyBeanReferenceProxyCreator(bf);
|
||||
|
||||
BeanWithFinalizer proxy = (BeanWithFinalizer) pc.createProxyIfPossible(descriptorFor(BeanWithFinalizer.class));
|
||||
|
||||
assertThat(BeanWithFinalizer.finalizerWasCalled, is(false));
|
||||
BeanWithFinalizer.class.getDeclaredMethod("finalize").invoke(proxy);
|
||||
assertThat(BeanWithFinalizer.finalizerWasCalled, is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void proxyMethodsDelegateToTargetBeanCausingSingletonRegistrationIfNecessary() throws Exception {
|
||||
bf.registerBeanDefinition("testBean",
|
||||
BeanDefinitionBuilder.rootBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "testBeanName").getBeanDefinition());
|
||||
EarlyBeanReferenceProxyCreator pc = new EarlyBeanReferenceProxyCreator(bf);
|
||||
TestBean proxy = (TestBean) pc.createProxyIfPossible(descriptorFor(TestBean.class));
|
||||
|
||||
assertThat(bf.containsBeanDefinition("testBean"), is(true));
|
||||
assertThat(bf.containsSingleton("testBean"), is(false));
|
||||
assertThat(proxy.getName(), equalTo("testBeanName"));
|
||||
assertThat(bf.containsSingleton("testBean"), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void beanAnnotatedMethodsReturnEarlyProxyAsWell() throws Exception {
|
||||
bf.registerBeanDefinition("componentWithInterfaceBeanMethod", new RootBeanDefinition(ComponentWithInterfaceBeanMethod.class));
|
||||
EarlyBeanReferenceProxyCreator pc = new EarlyBeanReferenceProxyCreator(bf);
|
||||
ComponentWithInterfaceBeanMethod proxy = (ComponentWithInterfaceBeanMethod) pc.createProxyIfPossible(descriptorFor(ComponentWithInterfaceBeanMethod.class));
|
||||
|
||||
ITestBean bean = proxy.aBeanMethod();
|
||||
assertThat(bean, instanceOf(EarlyBeanReferenceProxy.class));
|
||||
assertThat(bf.containsBeanDefinition("componentWithInterfaceBeanMethod"), is(true));
|
||||
assertThat("calling a @Bean method on an EarlyBeanReferenceProxy object " +
|
||||
"should not cause its instantation/registration",
|
||||
bf.containsSingleton("componentWithInterfaceBeanMethod"), is(false));
|
||||
|
||||
Object obj = proxy.normalInstanceMethod();
|
||||
assertThat(bf.containsSingleton("componentWithInterfaceBeanMethod"), is(true));
|
||||
assertThat(obj, not(instanceOf(EarlyBeanReferenceProxy.class)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void proxiesReturnedFromBeanAnnotatedMethodsDereferenceAndDelegateToTheirTargetBean() throws Exception {
|
||||
bf.registerBeanDefinition("componentWithConcreteBeanMethod", new RootBeanDefinition(ComponentWithConcreteBeanMethod.class));
|
||||
RootBeanDefinition beanMethodBeanDef = new RootBeanDefinition();
|
||||
beanMethodBeanDef.setFactoryBeanName("componentWithConcreteBeanMethod");
|
||||
beanMethodBeanDef.setFactoryMethodName("aBeanMethod");
|
||||
bf.registerBeanDefinition("aBeanMethod", beanMethodBeanDef);
|
||||
EarlyBeanReferenceProxyCreator pc = new EarlyBeanReferenceProxyCreator(bf);
|
||||
ComponentWithConcreteBeanMethod proxy = (ComponentWithConcreteBeanMethod) pc.createProxyIfPossible(descriptorFor(ComponentWithConcreteBeanMethod.class));
|
||||
|
||||
TestBean bean = proxy.aBeanMethod();
|
||||
assertThat(bean.getName(), equalTo("concrete"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void interfaceBeansAreProxied() throws Exception {
|
||||
EarlyBeanReferenceProxyCreator pc = new EarlyBeanReferenceProxyCreator(bf);
|
||||
ITestBean proxy = (ITestBean) pc.createProxyIfPossible(descriptorFor(ITestBean.class));
|
||||
|
||||
assertThat(proxy, instanceOf(EarlyBeanReferenceProxy.class));
|
||||
assertThat(AopUtils.isCglibProxyClass(proxy.getClass()), is(true));
|
||||
assertEquals(
|
||||
"interface-based bean proxies should have Object as superclass",
|
||||
proxy.getClass().getSuperclass(), Object.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void concreteBeansAreProxied() throws Exception {
|
||||
EarlyBeanReferenceProxyCreator pc = new EarlyBeanReferenceProxyCreator(bf);
|
||||
TestBean proxy = (TestBean) pc.createProxyIfPossible(descriptorFor(TestBean.class));
|
||||
|
||||
assertThat(proxy, instanceOf(EarlyBeanReferenceProxy.class));
|
||||
assertThat(AopUtils.isCglibProxyClass(proxy.getClass()), is(true));
|
||||
assertEquals(
|
||||
"concrete bean proxies should have the bean class as superclass",
|
||||
proxy.getClass().getSuperclass(), TestBean.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void beanAnnotatedMethodsWithInterfaceReturnTypeAreProxied() throws Exception {
|
||||
bf.registerBeanDefinition("componentWithInterfaceBeanMethod", new RootBeanDefinition(ComponentWithInterfaceBeanMethod.class));
|
||||
EarlyBeanReferenceProxyCreator pc = new EarlyBeanReferenceProxyCreator(bf);
|
||||
ComponentWithInterfaceBeanMethod proxy = (ComponentWithInterfaceBeanMethod) pc.createProxyIfPossible(descriptorFor(ComponentWithInterfaceBeanMethod.class));
|
||||
|
||||
ITestBean bean = proxy.aBeanMethod();
|
||||
assertThat(bean, instanceOf(EarlyBeanReferenceProxy.class));
|
||||
assertThat(AopUtils.isCglibProxyClass(bean.getClass()), is(true));
|
||||
assertEquals(
|
||||
"interface-based bean proxies should have Object as superclass",
|
||||
bean.getClass().getSuperclass(), Object.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void beanAnnotatedMethodsWithConcreteReturnTypeAreProxied() throws Exception {
|
||||
bf.registerBeanDefinition("componentWithConcreteBeanMethod", new RootBeanDefinition(ComponentWithConcreteBeanMethod.class));
|
||||
EarlyBeanReferenceProxyCreator pc = new EarlyBeanReferenceProxyCreator(bf);
|
||||
ComponentWithConcreteBeanMethod proxy = (ComponentWithConcreteBeanMethod) pc.createProxyIfPossible(descriptorFor(ComponentWithConcreteBeanMethod.class));
|
||||
|
||||
TestBean bean = proxy.aBeanMethod();
|
||||
assertThat(bean, instanceOf(EarlyBeanReferenceProxy.class));
|
||||
assertThat(AopUtils.isCglibProxyClass(bean.getClass()), is(true));
|
||||
assertEquals(
|
||||
"concrete bean proxies should have the bean class as superclass",
|
||||
bean.getClass().getSuperclass(), TestBean.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void attemptToProxyClassMissingNoArgConstructorFailsGracefully() throws Exception {
|
||||
EarlyBeanReferenceProxyCreator pc = new EarlyBeanReferenceProxyCreator(bf);
|
||||
try {
|
||||
pc.createProxyIfPossible(descriptorFor(BeanMissingNoArgConstructor.class));
|
||||
fail("expected ProxyCreationException");
|
||||
} catch(ProxyCreationException ex) {
|
||||
assertThat(ex.getMessage(),
|
||||
equalTo(format(MISSING_NO_ARG_CONSTRUCTOR_ERROR_MESSAGE, BeanMissingNoArgConstructor.class.getName())));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void attemptToProxyClassWithPrivateNoArgConstructorFailsGracefully() throws Exception {
|
||||
EarlyBeanReferenceProxyCreator pc = new EarlyBeanReferenceProxyCreator(bf);
|
||||
try {
|
||||
pc.createProxyIfPossible(descriptorFor(BeanWithPrivateNoArgConstructor.class));
|
||||
fail("expected ProxyCreationException");
|
||||
} catch(ProxyCreationException ex) {
|
||||
assertThat(ex.getMessage(),
|
||||
equalTo(format(PRIVATE_NO_ARG_CONSTRUCTOR_ERROR_MESSAGE, BeanWithPrivateNoArgConstructor.class.getName())));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void attemptToProxyFinalClassReturnsNonProxiedInstance() throws Exception {
|
||||
bf.registerBeanDefinition("finalBean", new RootBeanDefinition(FinalBean.class));
|
||||
EarlyBeanReferenceProxyCreator pc = new EarlyBeanReferenceProxyCreator(bf);
|
||||
Object bean = pc.createProxyIfPossible(descriptorFor(FinalBean.class));
|
||||
assertThat(bean, instanceOf(FinalBean.class));
|
||||
assertThat(bean, not(instanceOf(EarlyBeanReferenceProxy.class)));
|
||||
}
|
||||
|
||||
private DependencyDescriptor descriptorFor(Class<?> paramType) throws Exception {
|
||||
@SuppressWarnings("unused")
|
||||
class C {
|
||||
void m(ITestBean p) { }
|
||||
void m(TestBean p) { }
|
||||
void m(BeanMissingNoArgConstructor p) { }
|
||||
void m(BeanWithPrivateNoArgConstructor p) { }
|
||||
void m(FinalBean p) { }
|
||||
void m(BeanWithFinalizer p) { }
|
||||
void m(ComponentWithConcreteBeanMethod p) { }
|
||||
void m(ComponentWithInterfaceBeanMethod p) { }
|
||||
}
|
||||
|
||||
Method targetMethod = C.class.getDeclaredMethod("m", new Class<?>[] { paramType });
|
||||
MethodParameter mp = new MethodParameter(targetMethod, 0);
|
||||
DependencyDescriptor dd = new DependencyDescriptor(mp, true, false);
|
||||
return dd;
|
||||
}
|
||||
|
||||
|
||||
static class BeanMissingNoArgConstructor {
|
||||
BeanMissingNoArgConstructor(Object o) { }
|
||||
}
|
||||
|
||||
|
||||
static class BeanWithPrivateNoArgConstructor {
|
||||
private BeanWithPrivateNoArgConstructor() { }
|
||||
}
|
||||
|
||||
|
||||
static final class FinalBean {
|
||||
}
|
||||
|
||||
|
||||
static class BeanWithFinalizer {
|
||||
static Boolean finalizerWasCalled = false;
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
finalizerWasCalled = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static class ComponentWithConcreteBeanMethod {
|
||||
@Bean
|
||||
public TestBean aBeanMethod() {
|
||||
return new TestBean("concrete");
|
||||
}
|
||||
|
||||
public Object normalInstanceMethod() {
|
||||
return new Object();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static class ComponentWithInterfaceBeanMethod {
|
||||
@Bean
|
||||
public ITestBean aBeanMethod() {
|
||||
return new TestBean("interface");
|
||||
}
|
||||
|
||||
public Object normalInstanceMethod() {
|
||||
return new Object();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.context.annotation;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.annotation.configuration.StubSpecification;
|
||||
import org.springframework.context.config.FeatureSpecification;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.mock.env.MockEnvironment;
|
||||
|
||||
public class FeatureConfigurationClassTests {
|
||||
|
||||
@Test(expected=FeatureMethodExecutionException.class)
|
||||
public void featureConfigurationClassesMustNotContainBeanAnnotatedMethods() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(FeatureConfigWithBeanAnnotatedMethod.class);
|
||||
ctx.refresh();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void featureMethodsMayAcceptResourceLoaderParameter() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.setDisplayName("enclosing app ctx");
|
||||
ctx.setEnvironment(new MockEnvironment().withProperty("foo", "bar"));
|
||||
ctx.register(FeatureMethodWithResourceLoaderParameter.class);
|
||||
ctx.refresh();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@FeatureConfiguration
|
||||
class FeatureConfigWithBeanAnnotatedMethod {
|
||||
/**
|
||||
* This is illegal use. @FeatureConfiguration classes cannot have @Bean methods.
|
||||
*/
|
||||
@Bean
|
||||
public TestBean testBean() {
|
||||
return new TestBean();
|
||||
}
|
||||
|
||||
/**
|
||||
* This will never get called. An exception will first be raised regarding the illegal @Bean method above.
|
||||
*/
|
||||
@Feature
|
||||
public FeatureSpecification feature() {
|
||||
return new StubSpecification();
|
||||
}
|
||||
}
|
||||
|
||||
@FeatureConfiguration
|
||||
class FeatureMethodWithResourceLoaderParameter {
|
||||
@Feature
|
||||
public FeatureSpecification feature(ResourceLoader rl,
|
||||
Environment e) {
|
||||
// prove that the injected Environment is that of the enclosing app context
|
||||
assertThat(e.getProperty("foo"), is("bar"));
|
||||
// prove that the injected ResourceLoader is actually the enclosing application context
|
||||
Object target = ((EarlyBeanReferenceProxy)rl).dereferenceTargetBean();
|
||||
assertThat(target, instanceOf(AnnotationConfigApplicationContext.class));
|
||||
assertThat(((AnnotationConfigApplicationContext)target).getDisplayName(), is("enclosing app ctx"));
|
||||
return new StubSpecification();
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:c="http://www.springframework.org/schema/c"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
|
||||
|
||||
<bean class="test.beans.TestBean" c:name="beanFromXml"/>
|
||||
|
||||
</beans>
|
||||
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.context.annotation;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
import static org.junit.Assert.assertNotSame;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.configuration.StubSpecification;
|
||||
import org.springframework.context.config.FeatureSpecification;
|
||||
|
||||
import test.beans.TestBean;
|
||||
|
||||
/**
|
||||
* Tests proving that @FeatureConfiguration classes may be use @ImportResource
|
||||
* and then parameter autowire beans declared in the imported resource(s).
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @since 3.1
|
||||
*/
|
||||
public class FeatureConfigurationImportResourceTests {
|
||||
|
||||
@Test
|
||||
public void importResourceFromFeatureConfiguration() {
|
||||
ApplicationContext ctx =
|
||||
new AnnotationConfigApplicationContext(ImportingFeatureConfig.class);
|
||||
TestBean testBean = ctx.getBean(TestBean.class);
|
||||
assertThat(testBean.getName(), equalTo("beanFromXml"));
|
||||
|
||||
// and just quickly prove that the target of the bean proxied for the Feature method
|
||||
// is indeed the same singleton instance as the one we just pulled from the container
|
||||
ImportingFeatureConfig ifc = ctx.getBean(ImportingFeatureConfig.class);
|
||||
TestBean proxyBean = ifc.testBean;
|
||||
assertThat(proxyBean, instanceOf(EarlyBeanReferenceProxy.class));
|
||||
assertNotSame(proxyBean, testBean);
|
||||
assertSame(((EarlyBeanReferenceProxy)proxyBean).dereferenceTargetBean(), testBean);
|
||||
}
|
||||
|
||||
@FeatureConfiguration
|
||||
@ImportResource("org/springframework/context/annotation/FeatureConfigurationImportResourceTests-context.xml")
|
||||
static class ImportingFeatureConfig {
|
||||
TestBean testBean;
|
||||
|
||||
@Feature
|
||||
public FeatureSpecification f(TestBean testBean) {
|
||||
this.testBean = testBean;
|
||||
return new StubSpecification();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.context.annotation;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.configuration.StubSpecification;
|
||||
import org.springframework.context.config.FeatureSpecification;
|
||||
|
||||
/**
|
||||
* Tests proving that @Configuration classes may @Import @FeatureConfiguration
|
||||
* classes, and vice versa.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @since 3.1
|
||||
*/
|
||||
public class FeatureConfigurationImportTests {
|
||||
|
||||
@Test
|
||||
public void importFeatureConfigurationFromConfiguration() {
|
||||
ConfigurableApplicationContext ctx =
|
||||
new AnnotationConfigApplicationContext(ImportingConfig.class);
|
||||
ImportedFeatureConfig ifc = ctx.getBean(ImportedFeatureConfig.class);
|
||||
assertThat(
|
||||
"@FeatureConfiguration class was imported and registered " +
|
||||
"as a bean but its @Feature method was never called",
|
||||
ifc.featureMethodWasCalled, is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void importConfigurationFromFeatureConfiguration() {
|
||||
ConfigurableApplicationContext ctx =
|
||||
new AnnotationConfigApplicationContext(ImportingFeatureConfig.class);
|
||||
ImportingFeatureConfig ifc = ctx.getBean(ImportingFeatureConfig.class);
|
||||
ImportedConfig ic = ctx.getBean(ImportedConfig.class);
|
||||
assertThat(
|
||||
"@FeatureConfiguration class was registered directly against " +
|
||||
"the container but its @Feature method was never called",
|
||||
ifc.featureMethodWasCalled, is(true));
|
||||
assertThat(
|
||||
"@Configuration class was @Imported but its @Bean method" +
|
||||
"was never registered / called",
|
||||
ic.beanMethodWasCalled, is(true));
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@Import(ImportedFeatureConfig.class)
|
||||
static class ImportingConfig {
|
||||
}
|
||||
|
||||
|
||||
@FeatureConfiguration
|
||||
static class ImportedFeatureConfig {
|
||||
boolean featureMethodWasCalled = false;
|
||||
|
||||
@Feature
|
||||
public FeatureSpecification f() {
|
||||
this.featureMethodWasCalled = true;
|
||||
return new StubSpecification();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
static class ImportedConfig {
|
||||
boolean beanMethodWasCalled = true;
|
||||
@Bean
|
||||
public TestBean testBean() {
|
||||
this.beanMethodWasCalled = true;
|
||||
return new TestBean();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@FeatureConfiguration
|
||||
@Import(ImportedConfig.class)
|
||||
static class ImportingFeatureConfig {
|
||||
boolean featureMethodWasCalled = false;
|
||||
|
||||
@Feature
|
||||
public FeatureSpecification f() {
|
||||
this.featureMethodWasCalled = true;
|
||||
return new StubSpecification();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.context.annotation;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.not;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.annotation.configuration.StubSpecification;
|
||||
import org.springframework.context.config.FeatureSpecification;
|
||||
|
||||
import test.beans.ITestBean;
|
||||
import test.beans.TestBean;
|
||||
|
||||
/**
|
||||
* Tests proving that @Feature methods may reference the product of @Bean methods.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @since 3.1
|
||||
*/
|
||||
public class FeatureMethodBeanReferenceTests {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(FeatureConfig.class, Config.class);
|
||||
ctx.refresh();
|
||||
|
||||
TestBean registeredBean = ctx.getBean("testBean", TestBean.class);
|
||||
TestBean proxiedBean = ctx.getBean(FeatureConfig.class).testBean;
|
||||
|
||||
assertThat(registeredBean, not(instanceOf(EarlyBeanReferenceProxy.class)));
|
||||
assertThat(proxiedBean, notNullValue());
|
||||
assertThat(proxiedBean, instanceOf(EarlyBeanReferenceProxy.class));
|
||||
assertThat(proxiedBean.getSpouse(), is(registeredBean.getSpouse()));
|
||||
}
|
||||
|
||||
|
||||
@FeatureConfiguration
|
||||
static class FeatureConfig {
|
||||
TestBean testBean;
|
||||
|
||||
@Feature
|
||||
public FeatureSpecification f(TestBean testBean) {
|
||||
this.testBean = testBean;
|
||||
return new StubSpecification();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
static class Config {
|
||||
@Bean
|
||||
public ITestBean testBean() {
|
||||
return new TestBean(new TestBean("mySpouse"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,192 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.context.annotation;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.not;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.context.annotation.configuration.StubSpecification;
|
||||
import org.springframework.context.config.FeatureSpecification;
|
||||
|
||||
import test.beans.ITestBean;
|
||||
import test.beans.TestBean;
|
||||
|
||||
/**
|
||||
* Tests that @Bean methods referenced from within @Feature methods
|
||||
* get proxied early to avoid premature instantiation of actual
|
||||
* bean instances.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @since 3.1
|
||||
*/
|
||||
public class FeatureMethodEarlyBeanProxyTests {
|
||||
|
||||
@Test
|
||||
public void earlyProxyCreationAndBeanRegistrationLifecycle() {
|
||||
AnnotationConfigApplicationContext ctx =
|
||||
new AnnotationConfigApplicationContext(FeatureConfig.class);
|
||||
|
||||
//
|
||||
// see additional assertions in FeatureConfig#feature()
|
||||
//
|
||||
|
||||
// sanity check that all the bean definitions we expecting are present
|
||||
assertThat(ctx.getBeanFactory().containsBeanDefinition("lazyHelperBean"), is(true));
|
||||
assertThat(ctx.getBeanFactory().containsBeanDefinition("eagerHelperBean"), is(true));
|
||||
assertThat(ctx.getBeanFactory().containsBeanDefinition("lazyPassthroughBean"), is(true));
|
||||
assertThat(ctx.getBeanFactory().containsBeanDefinition("eagerPassthroughBean"), is(true));
|
||||
|
||||
|
||||
// the lazy helper bean had methods invoked during feature method execution. it should be registered
|
||||
assertThat(ctx.getBeanFactory().containsSingleton("lazyHelperBean"), is(true));
|
||||
|
||||
// the eager helper bean had methods invoked but should be registered in any case is it is non-lazy
|
||||
assertThat(ctx.getBeanFactory().containsSingleton("eagerHelperBean"), is(true));
|
||||
|
||||
// the lazy passthrough bean was referenced in the feature method, but never invoked. it should not be registered
|
||||
assertThat(ctx.getBeanFactory().containsSingleton("lazyPassthroughBean"), is(false));
|
||||
|
||||
// the eager passthrough bean should be registered in any case as it is non-lazy
|
||||
assertThat(ctx.getBeanFactory().containsSingleton("eagerPassthroughBean"), is(true));
|
||||
|
||||
|
||||
// now actually fetch all the beans. none should be proxies
|
||||
assertThat(ctx.getBean("lazyHelperBean"), not(instanceOf(EarlyBeanReferenceProxy.class)));
|
||||
assertThat(ctx.getBean("eagerHelperBean"), not(instanceOf(EarlyBeanReferenceProxy.class)));
|
||||
assertThat(ctx.getBean("lazyPassthroughBean"), not(instanceOf(EarlyBeanReferenceProxy.class)));
|
||||
assertThat(ctx.getBean("eagerPassthroughBean"), not(instanceOf(EarlyBeanReferenceProxy.class)));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void earlyProxyBeansMayBeInterfaceBasedOrConcrete() {
|
||||
new AnnotationConfigApplicationContext(FeatureConfigReferencingNonInterfaceBeans.class);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@FeatureConfiguration
|
||||
@Import(TestBeanConfig.class)
|
||||
class FeatureConfig implements BeanFactoryAware {
|
||||
private DefaultListableBeanFactory beanFactory;
|
||||
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = (DefaultListableBeanFactory)beanFactory;
|
||||
}
|
||||
|
||||
@Feature
|
||||
public StubSpecification feature(TestBeanConfig beans) {
|
||||
|
||||
assertThat(
|
||||
"The @Configuration class instance itself should be an early-ref proxy",
|
||||
beans, instanceOf(EarlyBeanReferenceProxy.class));
|
||||
|
||||
// invocation of @Bean methods within @Feature methods should return proxies
|
||||
ITestBean lazyHelperBean = beans.lazyHelperBean();
|
||||
ITestBean eagerHelperBean = beans.eagerHelperBean();
|
||||
ITestBean lazyPassthroughBean = beans.lazyPassthroughBean();
|
||||
ITestBean eagerPassthroughBean = beans.eagerPassthroughBean();
|
||||
|
||||
assertThat(lazyHelperBean, instanceOf(EarlyBeanReferenceProxy.class));
|
||||
assertThat(eagerHelperBean, instanceOf(EarlyBeanReferenceProxy.class));
|
||||
assertThat(lazyPassthroughBean, instanceOf(EarlyBeanReferenceProxy.class));
|
||||
assertThat(eagerPassthroughBean, instanceOf(EarlyBeanReferenceProxy.class));
|
||||
|
||||
// but at this point, the proxy instances should not have
|
||||
// been registered as singletons with the container.
|
||||
assertThat(this.beanFactory.containsSingleton("lazyHelperBean"), is(false));
|
||||
assertThat(this.beanFactory.containsSingleton("eagerHelperBean"), is(false));
|
||||
assertThat(this.beanFactory.containsSingleton("lazyPassthroughBean"), is(false));
|
||||
assertThat(this.beanFactory.containsSingleton("eagerPassthroughBean"), is(false));
|
||||
|
||||
// invoking a method on the proxy should cause it to pass through
|
||||
// to the container, instantiate the actual bean in question and
|
||||
// register that actual underlying instance as a singleton.
|
||||
assertThat(lazyHelperBean.getName(), equalTo("lazyHelper"));
|
||||
assertThat(eagerHelperBean.getName(), equalTo("eagerHelper"));
|
||||
|
||||
assertThat(this.beanFactory.containsSingleton("lazyHelperBean"), is(true));
|
||||
assertThat(this.beanFactory.containsSingleton("eagerHelperBean"), is(true));
|
||||
|
||||
// since no methods were called on the passthrough beans, they should remain
|
||||
// uncreated / unregistered.
|
||||
assertThat(this.beanFactory.containsSingleton("lazyPassthroughBean"), is(false));
|
||||
assertThat(this.beanFactory.containsSingleton("eagerPassthroughBean"), is(false));
|
||||
|
||||
return new StubSpecification();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
class TestBeanConfig {
|
||||
|
||||
@Lazy @Bean
|
||||
public ITestBean lazyHelperBean() {
|
||||
return new TestBean("lazyHelper");
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ITestBean eagerHelperBean() {
|
||||
return new TestBean("eagerHelper");
|
||||
}
|
||||
|
||||
@Lazy @Bean
|
||||
public ITestBean lazyPassthroughBean() {
|
||||
return new TestBean("lazyPassthrough");
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ITestBean eagerPassthroughBean() {
|
||||
return new TestBean("eagerPassthrough");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@FeatureConfiguration
|
||||
@Import(NonInterfaceBeans.class)
|
||||
class FeatureConfigReferencingNonInterfaceBeans {
|
||||
@Feature
|
||||
public FeatureSpecification feature1(NonInterfaceBeans beans) throws Throwable {
|
||||
beans.testBean();
|
||||
return new StubSpecification();
|
||||
}
|
||||
|
||||
@Feature
|
||||
public FeatureSpecification feature2(TestBean testBean) throws Throwable {
|
||||
return new StubSpecification();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
class NonInterfaceBeans {
|
||||
@Bean
|
||||
public TestBean testBean() {
|
||||
return new TestBean("invalid");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,113 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.context.annotation;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.annotation.configuration.StubSpecification;
|
||||
import org.springframework.context.config.FeatureSpecification;
|
||||
|
||||
import test.beans.TestBean;
|
||||
|
||||
/**
|
||||
* Tests proving that @Feature methods may reference the product of @Bean methods.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @since 3.1
|
||||
*/
|
||||
public class FeatureMethodErrorTests {
|
||||
|
||||
@Test
|
||||
public void incorrectReturnType() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(FeatureConfig.class);
|
||||
try {
|
||||
ctx.refresh();
|
||||
fail("expected exception");
|
||||
} catch (FeatureMethodExecutionException ex) {
|
||||
assertThat(ex.getCause().getMessage(),
|
||||
equalTo("Return type for @Feature method FeatureConfig.f() must be " +
|
||||
"assignable to FeatureSpecification"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void voidReturnType() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(VoidFeatureConfig.class);
|
||||
try {
|
||||
ctx.refresh();
|
||||
fail("expected exception");
|
||||
} catch (FeatureMethodExecutionException ex) {
|
||||
assertThat(ex.getCause().getMessage(),
|
||||
equalTo("Return type for @Feature method VoidFeatureConfig.f() must be " +
|
||||
"assignable to FeatureSpecification"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void containsBeanMethod() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(FeatureConfigWithBeanMethod.class);
|
||||
try {
|
||||
ctx.refresh();
|
||||
fail("expected exception");
|
||||
} catch (FeatureMethodExecutionException ex) {
|
||||
assertThat(ex.getMessage(),
|
||||
equalTo("@FeatureConfiguration classes must not contain @Bean-annotated methods. " +
|
||||
"FeatureConfigWithBeanMethod.testBean() is annotated with @Bean and must " +
|
||||
"be removed in order to proceed. Consider moving this method into a dedicated " +
|
||||
"@Configuration class and injecting the bean as a parameter into any @Feature " +
|
||||
"method(s) that need it."));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@FeatureConfiguration
|
||||
static class FeatureConfig {
|
||||
@Feature
|
||||
public Object f() {
|
||||
return new StubSpecification();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@FeatureConfiguration
|
||||
static class VoidFeatureConfig {
|
||||
@Feature
|
||||
public void f() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@FeatureConfiguration
|
||||
static class FeatureConfigWithBeanMethod {
|
||||
@Feature
|
||||
public FeatureSpecification f() {
|
||||
return new StubSpecification();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TestBean testBean() {
|
||||
return new TestBean();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.context.annotation;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.annotation.configuration.StubSpecification;
|
||||
import org.springframework.context.config.FeatureSpecification;
|
||||
|
||||
import test.beans.ITestBean;
|
||||
import test.beans.TestBean;
|
||||
|
||||
/**
|
||||
* Tests proving that @Feature methods may reference beans using @Qualifier
|
||||
* as a parameter annotation.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @since 3.1
|
||||
*/
|
||||
public class FeatureMethodQualifiedBeanReferenceTests {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(Features.class, TestBeans.class);
|
||||
ctx.refresh();
|
||||
}
|
||||
|
||||
@FeatureConfiguration
|
||||
static class Features {
|
||||
|
||||
@Feature
|
||||
public FeatureSpecification f(@Qualifier("testBean1") ITestBean testBean) {
|
||||
assertThat(testBean.getName(), equalTo("one"));
|
||||
return new StubSpecification();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class TestBeans {
|
||||
@Bean
|
||||
public ITestBean testBean1() {
|
||||
return new TestBean("one");
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ITestBean testBean2() {
|
||||
return new TestBean("two");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,135 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.context.annotation;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.configuration.StubSpecification;
|
||||
|
||||
/**
|
||||
* Tests ensuring that @Feature methods can accept @Value-annoted
|
||||
* parameters, particularly String types. SPR-7974 revealed this
|
||||
* was failing due to attempting to proxy objects of type String,
|
||||
* which cannot be done.
|
||||
*
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class FeatureMethodValueInjectionTests {
|
||||
|
||||
@Test
|
||||
public void control() {
|
||||
System.setProperty("foo", "bar");
|
||||
System.setProperty("num", "2");
|
||||
Config config = new AnnotationConfigApplicationContext(Config.class).getBean(Config.class);
|
||||
System.clearProperty("foo");
|
||||
System.clearProperty("num");
|
||||
assertThat(config.foo, is("bar"));
|
||||
assertThat(config.num, is(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void spelValueInjection() {
|
||||
System.setProperty("foo", "bar");
|
||||
new AnnotationConfigApplicationContext(SpelValueInjectionFeatureConfig.class);
|
||||
System.clearProperty("foo");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void spelIntValueInjection() {
|
||||
System.setProperty("num", "5");
|
||||
new AnnotationConfigApplicationContext(SpelIntValueInjectionFeatureConfig.class);
|
||||
System.clearProperty("num");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stringBeanInjection() {
|
||||
new AnnotationConfigApplicationContext(StringBeanConfig.class, StringBeanInjectionByTypeFeatureConfig.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void qualifiedStringBeanInjection() {
|
||||
new AnnotationConfigApplicationContext(StringBeanSubConfig.class, StringBeanInjectionByQualifierFeatureConfig.class);
|
||||
}
|
||||
|
||||
|
||||
@FeatureConfiguration
|
||||
static class SpelValueInjectionFeatureConfig {
|
||||
@Feature
|
||||
public StubSpecification feature(@Value("#{environment['foo']}") String foo) {
|
||||
return new StubSpecification();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@FeatureConfiguration
|
||||
static class SpelIntValueInjectionFeatureConfig {
|
||||
@Feature
|
||||
public StubSpecification feature(@Value("#{environment['num']}") int num) {
|
||||
assertThat(num, is(5));
|
||||
return new StubSpecification();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
static class StringBeanConfig {
|
||||
@Bean
|
||||
public String stringBean() {
|
||||
return "sb";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
static class StringBeanSubConfig extends StringBeanConfig {
|
||||
@Bean
|
||||
public String stringBean2() {
|
||||
return "sb2";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@FeatureConfiguration
|
||||
static class StringBeanInjectionByTypeFeatureConfig {
|
||||
@Feature
|
||||
public StubSpecification feature(String string) {
|
||||
assertThat(string, is("sb"));
|
||||
return new StubSpecification();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@FeatureConfiguration
|
||||
static class StringBeanInjectionByQualifierFeatureConfig {
|
||||
@Feature
|
||||
public StubSpecification feature(@Qualifier("stringBean2") String string) {
|
||||
assertThat(string, is("sb2"));
|
||||
return new StubSpecification();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
static class Config {
|
||||
@Value("#{environment['foo']}") String foo;
|
||||
@Value("#{environment['num']}") int num;
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.context.annotation;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.annotation.configuration.StubSpecification;
|
||||
import org.springframework.context.config.SpecificationContext;
|
||||
import org.springframework.context.config.FeatureSpecification;
|
||||
import org.springframework.context.config.FeatureSpecificationExecutor;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Simple tests to ensure that @Feature methods are invoked and that the
|
||||
* resulting returned {@link FeatureSpecification} object is delegated to
|
||||
* the correct {@link FeatureSpecificationExecutor}.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @since 3.1
|
||||
*/
|
||||
public class SimpleFeatureMethodProcessingTests {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(FeatureConfig.class);
|
||||
assertThat(MySpecificationExecutor.executeMethodWasCalled, is(false));
|
||||
ctx.refresh();
|
||||
assertThat(MySpecificationExecutor.executeMethodWasCalled, is(true));
|
||||
}
|
||||
|
||||
@FeatureConfiguration
|
||||
static class FeatureConfig {
|
||||
@Feature
|
||||
public FeatureSpecification f() {
|
||||
return new StubSpecification(MySpecificationExecutor.class);
|
||||
}
|
||||
}
|
||||
|
||||
static class MySpecificationExecutor implements FeatureSpecificationExecutor {
|
||||
static boolean executeMethodWasCalled = false;
|
||||
public void execute(FeatureSpecification spec, SpecificationContext specificationContext) {
|
||||
Assert.state(executeMethodWasCalled == false);
|
||||
executeMethodWasCalled = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<bean class="org.springframework.context.annotation.configuration.ColourHolder"/>
|
||||
|
||||
</beans>
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.context.annotation.configuration;
|
||||
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Suite;
|
||||
import org.junit.runners.Suite.SuiteClasses;
|
||||
|
||||
import org.springframework.context.annotation.FeatureMethodEarlyBeanProxyTests;
|
||||
|
||||
/**
|
||||
* Test suite that groups all tests related to @Feature method lifecycle issues.
|
||||
*
|
||||
* @author Chris Beams
|
||||
*/
|
||||
@RunWith(Suite.class)
|
||||
@SuiteClasses({
|
||||
FeatureMethodEarlyBeanProxyTests.class,
|
||||
ConfigurationClassWithPlaceholderConfigurerBeanTests.class
|
||||
})
|
||||
public class FeatureMethodLifecycleIssueTestSuite {
|
||||
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.context.annotation.configuration;
|
||||
|
||||
import org.springframework.beans.factory.parsing.ProblemCollector;
|
||||
import org.springframework.context.config.AbstractFeatureSpecification;
|
||||
import org.springframework.context.config.FeatureSpecification;
|
||||
import org.springframework.context.config.FeatureSpecificationExecutor;
|
||||
import org.springframework.context.config.SpecificationContext;
|
||||
|
||||
public class StubSpecification extends AbstractFeatureSpecification {
|
||||
|
||||
public StubSpecification() {
|
||||
this(StubSpecificationExecutor.class);
|
||||
}
|
||||
|
||||
public StubSpecification(Class<? extends FeatureSpecificationExecutor> excecutorType) {
|
||||
super(excecutorType);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doValidate(ProblemCollector problems) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class StubSpecificationExecutor implements FeatureSpecificationExecutor {
|
||||
|
||||
public void execute(FeatureSpecification spec, SpecificationContext specificationContext) {
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user