+ Moving .config.java module -> .context

This commit is contained in:
Chris Beams
2009-03-23 04:48:04 +00:00
parent 63b5c48461
commit cd50e45645
62 changed files with 137 additions and 25 deletions

View File

@@ -0,0 +1,62 @@
/*
* Copyright 2002-2009 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 static org.junit.Assert.*;
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.*;
import org.junit.Test;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.support.ConfigurationClassPostProcessor;
/**
* Covers the somewhat unlilely case of a {@link Configuration} class being declared
* as an abstract {@link BeanDefinition}.
*
* @author Chris Beams
* @see BeanDefinition#isAbstract()
*/
public class AbstractBeanDefinitionConfigurationClassTests {
@SuppressWarnings("unused")
@Test
public void abstractConfigurationClassBeanDefinitionsAreIgnored() {
@Configuration class Abstract { @Bean Object foo1() { return null; } }
@Configuration class Concrete { @Bean Object foo2() { return null; } }
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
factory.registerBeanDefinition("abstract",
rootBeanDefinition(Abstract.class).setAbstract(true).getBeanDefinition());
factory.registerBeanDefinition("concrete",
rootBeanDefinition(Concrete.class).setAbstract(false).getBeanDefinition());
new ConfigurationClassPostProcessor().postProcessBeanFactory(factory);
assertTrue("abstract configuration should be CGLIB-enhanced",
AopUtils.isCglibProxyClassName(factory.getBeanDefinition("abstract").getBeanClassName()));
assertTrue("concrete configuration should be CGLIB-enhanced",
AopUtils.isCglibProxyClassName(factory.getBeanDefinition("concrete").getBeanClassName()));
assertFalse("abstract configuration's @Bean method should not be registered",
factory.containsBeanDefinition("foo1"));
assertTrue("concrete configuration's @Bean method should be registered",
factory.containsBeanDefinition("foo2"));
}
}

View File

@@ -0,0 +1,15 @@
package org.springframework.context.annotation.configuration;
import org.junit.Before;
public abstract class AbstractJavaConfigTests {
@Before
public void setUp() {
}
// protected
}

View File

@@ -0,0 +1,79 @@
package org.springframework.context.annotation.configuration;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.junit.Test;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.support.ConfigurationClassPostProcessor;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.io.ClassPathResource;
import test.beans.TestBean;
public class AspectTests {
private void assertAdviceWasApplied(Class<?> configClass) {
GenericApplicationContext ctx = new GenericApplicationContext(
new XmlBeanFactory(new ClassPathResource("aspectj-autoproxy-config.xml", AspectTests.class)));
ctx.addBeanFactoryPostProcessor(new ConfigurationClassPostProcessor());
ctx.registerBeanDefinition("config", new RootBeanDefinition(configClass));
ctx.refresh();
TestBean testBean = ctx.getBean("testBean", TestBean.class);
assertThat(testBean.getName(), equalTo("name"));
testBean.absquatulate();
assertThat(testBean.getName(), equalTo("advisedName"));
}
@Test
public void aspectAnnotatedConfiguration() {
assertAdviceWasApplied(AspectConfig.class);
}
@Test
public void configurationIncludesAspect() {
assertAdviceWasApplied(ConfigurationWithAspect.class);
}
@Aspect
@Configuration
static class AspectConfig {
@Bean
public TestBean testBean() {
return new TestBean("name");
}
@Before("execution(* test.beans.TestBean.absquatulate(..)) && target(testBean)")
public void touchBean(TestBean testBean) {
testBean.setName("advisedName");
}
}
@Configuration
static class ConfigurationWithAspect {
@Bean
public TestBean testBean() {
return new TestBean("name");
}
@Bean
public NameChangingAspect nameChangingAspect() {
return new NameChangingAspect();
}
}
@Aspect
static class NameChangingAspect {
@Before("execution(* test.beans.TestBean.absquatulate(..)) && target(testBean)")
public void touchBean(TestBean testBean) {
testBean.setName("advisedName");
}
}
}

View File

@@ -0,0 +1,69 @@
package org.springframework.context.annotation.configuration;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import test.beans.Colour;
import test.beans.TestBean;
public class AutowiredConfigurationTests {
public @Test
void test() {
ClassPathXmlApplicationContext factory = new ClassPathXmlApplicationContext(
AutowiredConfigurationTests.class.getSimpleName() + ".xml", AutowiredConfigurationTests.class);
assertThat(factory.getBean("colour", Colour.class), equalTo(Colour.RED));
assertThat(factory.getBean("testBean", TestBean.class).getName(), equalTo(Colour.RED.toString()));
}
@Configuration
static class AutowiredConfig {
private @Autowired
Colour colour;
public @Bean
TestBean testBean() {
return new TestBean(colour.toString());
}
}
@Configuration
static class ColorConfig {
public @Bean
Colour colour() {
return Colour.RED;
}
}
public @Test
void testValueInjection() {
System.setProperty("myProp", "foo");
ClassPathXmlApplicationContext factory = new ClassPathXmlApplicationContext(
"ValueInjectionTests.xml", AutowiredConfigurationTests.class);
TestBean testBean = factory.getBean("testBean", TestBean.class);
assertThat(testBean.getName(), equalTo("foo"));
}
@Configuration
static class ValueConfig {
@Value("#{systemProperties.myProp}")
private String name = "default";
public @Bean
TestBean testBean() {
return new TestBean(name);
}
}
}

View File

@@ -0,0 +1,15 @@
<?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
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"
xmlns:context="http://www.springframework.org/schema/context">
<context:annotation-config/>
<bean class="org.springframework.context.annotation.support.ConfigurationClassPostProcessor"/>
<bean class="org.springframework.context.annotation.configuration.AutowiredConfigurationTests$AutowiredConfig"/>
<bean class="org.springframework.context.annotation.configuration.AutowiredConfigurationTests$ColorConfig"/>
</beans>

View File

@@ -0,0 +1,159 @@
package org.springframework.context.annotation.configuration;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.*;
import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.StandardScopes;
import org.springframework.context.annotation.support.ConfigurationClassPostProcessor;
import test.beans.ITestBean;
import test.beans.TestBean;
public class BasicTests {
/**
* Creates a new {@link BeanFactory}, populates it with a {@link BeanDefinition} for
* each of the given {@link Configuration} <var>configClasses</var>, and then
* post-processes the factory using JavaConfig's {@link ConfigurationClassPostProcessor}.
* When complete, the factory is ready to service requests for any {@link Bean} methods
* declared by <var>configClasses</var>.
*
* @param configClasses the {@link Configuration} classes under test. may be an empty
* list.
*
* @return fully initialized and post-processed {@link BeanFactory}
*/
private static BeanFactory initBeanFactory(Class<?>... configClasses) {
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
for (Class<?> configClass : configClasses) {
String configBeanName = configClass.getName();
factory.registerBeanDefinition(configBeanName, rootBeanDefinition(configClass).getBeanDefinition());
}
new ConfigurationClassPostProcessor().postProcessBeanFactory(factory);
factory.addBeanPostProcessor(new AutowiredAnnotationBeanPostProcessor());
return factory;
}
@Test
public void customBeanNameIsRespected() {
BeanFactory factory = initBeanFactory(ConfigWithBeanWithCustomName.class);
assertSame(factory.getBean("customName"), ConfigWithBeanWithCustomName.testBean);
// method name should not be registered
try {
factory.getBean("methodName");
fail("bean should not have been registered with 'methodName'");
} catch (NoSuchBeanDefinitionException ex) { /* expected */ }
}
@Configuration
static class ConfigWithBeanWithCustomName {
static TestBean testBean = new TestBean();
@Bean(name="customName")
public TestBean methodName() {
return testBean;
}
}
@Test
public void aliasesAreRespected() {
BeanFactory factory = initBeanFactory(ConfigWithBeanWithAliases.class);
assertSame(factory.getBean("name1"), ConfigWithBeanWithAliases.testBean);
String[] aliases = factory.getAliases("name1");
for(String alias : aliases)
assertSame(factory.getBean(alias), ConfigWithBeanWithAliases.testBean);
// method name should not be registered
try {
factory.getBean("methodName");
fail("bean should not have been registered with 'methodName'");
} catch (NoSuchBeanDefinitionException ex) { /* expected */ }
}
@Configuration
static class ConfigWithBeanWithAliases {
static TestBean testBean = new TestBean();
@Bean(name={"name1", "alias1", "alias2", "alias3"})
public TestBean methodName() {
return testBean;
}
}
@Test(expected=BeanDefinitionParsingException.class)
public void testFinalBeanMethod() {
initBeanFactory(ConfigWithFinalBean.class);
}
@Configuration
static class ConfigWithFinalBean {
public final @Bean TestBean testBean() {
return new TestBean();
}
}
@Test
public void simplestPossibleConfiguration() {
BeanFactory factory = initBeanFactory(SimplestPossibleConfig.class);
String stringBean = factory.getBean("stringBean", String.class);
assertThat(stringBean, equalTo("foo"));
}
@Configuration
static class SimplestPossibleConfig {
public @Bean String stringBean() {
return "foo";
}
}
@Test
public void configurationWithPrototypeScopedBeans() {
BeanFactory factory = initBeanFactory(ConfigWithPrototypeBean.class);
TestBean foo = factory.getBean("foo", TestBean.class);
ITestBean bar = factory.getBean("bar", ITestBean.class);
ITestBean baz = factory.getBean("baz", ITestBean.class);
assertThat(foo.getSpouse(), sameInstance(bar));
assertThat(bar.getSpouse(), not(sameInstance(baz)));
}
@Configuration
static class ConfigWithPrototypeBean {
public @Bean TestBean foo() {
TestBean foo = new TestBean("foo");
foo.setSpouse(bar());
return foo;
}
public @Bean TestBean bar() {
TestBean bar = new TestBean("bar");
bar.setSpouse(baz());
return bar;
}
@Bean @Scope(StandardScopes.PROTOTYPE)
public TestBean baz() {
return new TestBean("bar");
}
}
}

View File

@@ -0,0 +1,275 @@
/*
* Copyright 2002-2008 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 static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import org.junit.Test;
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.support.ConfigurationClassPostProcessor;
import test.beans.ITestBean;
import test.beans.TestBean;
/**
* System tests for {@link Import} annotation support.
*
* @author Chris Beams
*/
public class ImportTests {
private DefaultListableBeanFactory processConfigurationClasses(Class<?>... classes) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
for (Class<?> clazz : classes)
beanFactory.registerBeanDefinition(clazz.getSimpleName(), new RootBeanDefinition(clazz));
new ConfigurationClassPostProcessor().postProcessBeanFactory(beanFactory);
return beanFactory;
}
private void assertBeanDefinitionCount(int expectedCount, Class<?>... classes) {
DefaultListableBeanFactory beanFactory = processConfigurationClasses(classes);
assertThat(beanFactory.getBeanDefinitionCount(), equalTo(expectedCount));
}
@Test
public void testProcessImports() {
int configClasses = 2;
int beansInClasses = 2;
assertBeanDefinitionCount((configClasses + beansInClasses), ConfigurationWithImportAnnotation.class);
}
@Configuration
@Import(OtherConfiguration.class)
static class ConfigurationWithImportAnnotation {
@Bean
public ITestBean one() {
return new TestBean();
}
}
@Configuration
static class OtherConfiguration {
@Bean
public ITestBean two() {
return new TestBean();
}
}
// ------------------------------------------------------------------------
@Test
public void testImportAnnotationWithTwoLevelRecursion() {
int configClasses = 2;
int beansInClasses = 3;
assertBeanDefinitionCount((configClasses + beansInClasses), AppConfig.class);
}
@Configuration
@Import(DataSourceConfig.class)
static class AppConfig {
@Bean
public ITestBean transferService() {
return new TestBean(accountRepository());
}
@Bean
public ITestBean accountRepository() {
return new TestBean();
}
}
@Configuration
static class DataSourceConfig {
@Bean
public ITestBean dataSourceA() {
return new TestBean();
}
}
// ------------------------------------------------------------------------
@Test
public void testImportAnnotationWithThreeLevelRecursion() {
int configClasses = 3;
int beansInClasses = 5;
assertBeanDefinitionCount((configClasses + beansInClasses), FirstLevel.class);
}
// ------------------------------------------------------------------------
@Test
public void testImportAnnotationWithMultipleArguments() {
int configClasses = 3;
int beansInClasses = 3;
assertBeanDefinitionCount((configClasses + beansInClasses),
WithMultipleArgumentsToImportAnnotation.class);
}
@Test
public void testImportAnnotationWithMultipleArgumentsResultingInOverriddenBeanDefinition() {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
beanFactory.registerBeanDefinition("config", new RootBeanDefinition(
WithMultipleArgumentsThatWillCauseDuplication.class));
new ConfigurationClassPostProcessor().postProcessBeanFactory(beanFactory);
assertThat(beanFactory.getBeanDefinitionCount(), equalTo(4));
assertThat(beanFactory.getBean("foo", ITestBean.class).getName(), equalTo("foo2"));
}
@Configuration
@Import( { Foo1.class, Foo2.class })
static class WithMultipleArgumentsThatWillCauseDuplication {
}
@Configuration
static class Foo1 {
@Bean
public ITestBean foo() {
return new TestBean("foo1");
}
}
@Configuration
static class Foo2 {
@Bean
public ITestBean foo() {
return new TestBean("foo2");
}
}
// ------------------------------------------------------------------------
@Test
public void testImportAnnotationOnInnerClasses() {
int configClasses = 2;
int beansInClasses = 2;
assertBeanDefinitionCount((configClasses + beansInClasses), OuterConfig.InnerConfig.class);
}
@Configuration
static class OuterConfig {
@Bean
String whatev() {
return "whatev";
}
@Configuration
@Import(ExternalConfig.class)
static class InnerConfig {
@Bean
public ITestBean innerBean() {
return new TestBean();
}
}
}
@Configuration
static class ExternalConfig {
@Bean
public ITestBean extBean() {
return new TestBean();
}
}
// ------------------------------------------------------------------------
@Configuration
@Import(SecondLevel.class)
static class FirstLevel {
@Bean
public TestBean m() {
return new TestBean();
}
}
@Configuration
@Import(ThirdLevel.class)
static class SecondLevel {
@Bean
public TestBean n() {
return new TestBean();
}
}
@Configuration
static class ThirdLevel {
@Bean
public ITestBean thirdLevelA() {
return new TestBean();
}
@Bean
public ITestBean thirdLevelB() {
return new TestBean();
}
@Bean
public ITestBean thirdLevelC() {
return new TestBean();
}
}
@Configuration
@Import( { LeftConfig.class, RightConfig.class })
static class WithMultipleArgumentsToImportAnnotation {
@Bean
public TestBean m() {
return new TestBean();
}
}
@Configuration
static class LeftConfig {
@Bean
public ITestBean left() {
return new TestBean();
}
}
@Configuration
static class RightConfig {
@Bean
public ITestBean right() {
return new TestBean();
}
}
// ------------------------------------------------------------------------
@Test(expected=BeanDefinitionParsingException.class)
public void testImportNonConfigurationAnnotationClassCausesError() {
processConfigurationClasses(ConfigAnnotated.class);
}
@Configuration
@Import(NonConfigAnnotated.class)
static class ConfigAnnotated { }
static class NonConfigAnnotated { }
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright 2002-2009 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 java.lang.annotation.Inherited;
import org.junit.Test;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.support.ConfigurationClassPostProcessor;
import test.beans.TestBean;
/**
* Tests that polymorphic Configuration classes need not explicitly redeclare the
* {@link Configuration} annotation. This respects the {@link Inherited} nature
* of the Configuration annotation, even though it's being detected via ASM.
*
* @author Chris Beams
*/
public class PolymorphicConfigurationTests {
@Test
public void subclassNeedNotDeclareConfigurationAnnotation() {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
beanFactory.registerBeanDefinition("config", new RootBeanDefinition(Config.class));
new ConfigurationClassPostProcessor().postProcessBeanFactory(beanFactory);
beanFactory.getBean("testBean", TestBean.class);
}
@Configuration
static class SuperConfig {
@Bean
public TestBean testBean() {
return new TestBean();
}
}
static class Config extends SuperConfig { }
}

View File

@@ -0,0 +1,438 @@
/*
* Copyright 2002-2009 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 static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.*;
import java.util.HashMap;
import java.util.Map;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.aop.scope.ScopedObject;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.context.annotation.StandardScopes;
import org.springframework.context.annotation.support.ConfigurationClassPostProcessor;
import org.springframework.context.support.GenericApplicationContext;
import test.beans.ITestBean;
import test.beans.TestBean;
/**
* Tests that scopes are properly supported by using a custom Scope implementations
* and scoped proxy {@link Bean} declarations.
*
* @author Costin Leau
* @author Chris Beams
*/
public class ScopingTests {
public static String flag = "1";
private static final String SCOPE = "my scope";
private CustomScope customScope;
private GenericApplicationContext ctx;
@Before
public void setUp() throws Exception {
customScope = new CustomScope();
ctx = createContext(customScope, ScopedConfigurationClass.class);
}
@After
public void tearDown() throws Exception {
ctx.close();
ctx = null;
customScope = null;
}
private GenericApplicationContext createContext(org.springframework.beans.factory.config.Scope customScope, Class<?> configClass) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
if(customScope != null)
beanFactory.registerScope(SCOPE, customScope);
beanFactory.registerBeanDefinition("config",
rootBeanDefinition(configClass).getBeanDefinition());
GenericApplicationContext ctx = new GenericApplicationContext(beanFactory);
ctx.addBeanFactoryPostProcessor(new ConfigurationClassPostProcessor());
ctx.refresh();
return ctx;
}
@Test
public void testScopeOnClasses() throws Exception {
genericTestScope("scopedClass");
}
@Test
public void testScopeOnInterfaces() throws Exception {
genericTestScope("scopedInterface");
}
@Test
public void testSameScopeOnDifferentBeans() throws Exception {
Object beanAInScope = ctx.getBean("scopedClass");
Object beanBInScope = ctx.getBean("scopedInterface");
assertNotSame(beanAInScope, beanBInScope);
customScope.createNewScope = true;
Object newBeanAInScope = ctx.getBean("scopedClass");
Object newBeanBInScope = ctx.getBean("scopedInterface");
assertNotSame(newBeanAInScope, newBeanBInScope);
assertNotSame(newBeanAInScope, beanAInScope);
assertNotSame(newBeanBInScope, beanBInScope);
}
@Test
public void testScopedProxyOnSingletonBeanMethod() throws Exception {
// should throw - scoped proxies should not be applied on singleton/prototype beans
try {
createContext(null, InvalidProxyOnPredefinedScopesConfiguration.class);
fail("exception expected");
} catch (BeanDefinitionParsingException ex) {
assertTrue(ex.getMessage().contains("scoped proxies cannot be created for singleton/prototype beans"));
}
}
@Test
public void testRawScopes() throws Exception {
String beanName = "scopedProxyInterface";
// get hidden bean
Object bean = ctx.getBean("scopedTarget." + beanName);
assertFalse(bean instanceof ScopedObject);
}
@Test
public void testScopedProxyConfiguration() throws Exception {
TestBean singleton = (TestBean) ctx.getBean("singletonWithScopedInterfaceDep");
ITestBean spouse = singleton.getSpouse();
assertTrue("scoped bean is not wrapped by the scoped-proxy", spouse instanceof ScopedObject);
String beanName = "scopedProxyInterface";
String scopedBeanName = "scopedTarget." + beanName;
// get hidden bean
assertEquals(flag, spouse.getName());
ITestBean spouseFromBF = (ITestBean) ctx.getBean(scopedBeanName);
assertEquals(spouse.getName(), spouseFromBF.getName());
// the scope proxy has kicked in
assertNotSame(spouse, spouseFromBF);
// create a new bean
customScope.createNewScope = true;
// get the bean again from the BF
spouseFromBF = (ITestBean) ctx.getBean(scopedBeanName);
// make sure the name has been updated
assertSame(spouse.getName(), spouseFromBF.getName());
assertNotSame(spouse, spouseFromBF);
// get the bean again
spouseFromBF = (ITestBean) ctx.getBean(scopedBeanName);
assertSame(spouse.getName(), spouseFromBF.getName());
}
@Test
public void testScopedProxyConfigurationWithClasses() throws Exception {
TestBean singleton = (TestBean) ctx.getBean("singletonWithScopedClassDep");
ITestBean spouse = singleton.getSpouse();
assertTrue("scoped bean is not wrapped by the scoped-proxy", spouse instanceof ScopedObject);
String beanName = "scopedProxyClass";
String scopedBeanName = "scopedTarget." + beanName;
// get hidden bean
assertEquals(flag, spouse.getName());
TestBean spouseFromBF = (TestBean) ctx.getBean(scopedBeanName);
assertEquals(spouse.getName(), spouseFromBF.getName());
// the scope proxy has kicked in
assertNotSame(spouse, spouseFromBF);
// create a new bean
customScope.createNewScope = true;
flag = "boo";
// get the bean again from the BF
spouseFromBF = (TestBean) ctx.getBean(scopedBeanName);
// make sure the name has been updated
assertSame(spouse.getName(), spouseFromBF.getName());
assertNotSame(spouse, spouseFromBF);
// get the bean again
spouseFromBF = (TestBean) ctx.getBean(scopedBeanName);
assertSame(spouse.getName(), spouseFromBF.getName());
}
@Test
public void testScopedConfigurationBeanDefinitionCount() throws Exception {
// count the beans
// 6 @Beans + 1 Configuration + 2 scoped proxy
assertThat(ctx.getBeanDefinitionCount(), equalTo(9));
}
// /**
// * SJC-254 caught a regression in handling scoped proxies starting in 1.0 m4.
// * The ScopedProxyFactoryBean object was having its scope set to that of its delegate
// * whereas it should have remained singleton.
// */
// @Test
// public void sjc254() {
// JavaConfigWebApplicationContext ctx = new JavaConfigWebApplicationContext();
// ctx.setConfigLocations(new String[] { ScopeTestConfiguration.class.getName() });
// ctx.refresh();
//
// // should be fine
// ctx.getBean(Bar.class);
//
// boolean threw = false;
// try {
// ctx.getBean(Foo.class);
// } catch (BeanCreationException ex) {
// if(ex.getCause() instanceof IllegalStateException) {
// threw = true;
// }
// }
// assertTrue(threw);
// }
@Configuration
static class ScopeTestConfiguration {
@Bean
@Scope(value=StandardScopes.SESSION, proxyMode=ScopedProxyMode.INTERFACES)
public Foo foo() {
return new Foo();
}
@Bean
public Bar bar() {
return new Bar(foo());
}
}
static class Foo {
public Foo() {
//System.out.println("created foo: " + this.getClass().getName());
}
public void doSomething() {
//System.out.println("interesting: " + this);
}
}
static class Bar {
private final Foo foo;
public Bar(Foo foo) {
this.foo = foo;
//System.out.println("created bar: " + this);
}
public Foo getFoo() {
return foo;
}
}
private void genericTestScope(String beanName) throws Exception {
String message = "scope is ignored";
Object bean1 = ctx.getBean(beanName);
Object bean2 = ctx.getBean(beanName);
assertSame(message, bean1, bean2);
Object bean3 = ctx.getBean(beanName);
assertSame(message, bean1, bean3);
// make the scope create a new object
customScope.createNewScope = true;
Object newBean1 = ctx.getBean(beanName);
assertNotSame(message, bean1, newBean1);
Object sameBean1 = ctx.getBean(beanName);
assertSame(message, newBean1, sameBean1);
// make the scope create a new object
customScope.createNewScope = true;
Object newBean2 = ctx.getBean(beanName);
assertNotSame(message, newBean1, newBean2);
// make the scope create a new object .. again
customScope.createNewScope = true;
Object newBean3 = ctx.getBean(beanName);
assertNotSame(message, newBean2, newBean3);
}
@Configuration
public static class InvalidProxyOnPredefinedScopesConfiguration {
@Bean @Scope(proxyMode=ScopedProxyMode.INTERFACES)
public Object invalidProxyOnPredefinedScopes() { return new Object(); }
}
@Configuration
public static class ScopedConfigurationClass {
@Bean
@Scope(SCOPE)
public TestBean scopedClass() {
TestBean tb = new TestBean();
tb.setName(flag);
return tb;
}
@Bean
@Scope(SCOPE)
public ITestBean scopedInterface() {
TestBean tb = new TestBean();
tb.setName(flag);
return tb;
}
@Bean
@Scope(value=SCOPE, proxyMode=ScopedProxyMode.TARGET_CLASS)
public ITestBean scopedProxyInterface() {
TestBean tb = new TestBean();
tb.setName(flag);
return tb;
}
@Bean
@Scope(value=SCOPE, proxyMode=ScopedProxyMode.TARGET_CLASS)
public TestBean scopedProxyClass() {
TestBean tb = new TestBean();
tb.setName(flag);
return tb;
}
@Bean
public TestBean singletonWithScopedClassDep() {
TestBean singleton = new TestBean();
singleton.setSpouse(scopedProxyClass());
return singleton;
}
@Bean
public TestBean singletonWithScopedInterfaceDep() {
TestBean singleton = new TestBean();
singleton.setSpouse(scopedProxyInterface());
return singleton;
}
}
}
/**
* Simple scope implementation which creates object based on a flag.
*
* @author Costin Leau
* @author Chris Beams
*/
class CustomScope implements org.springframework.beans.factory.config.Scope {
public boolean createNewScope = true;
private Map<String, Object> beans = new HashMap<String, Object>();
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.config.Scope#get(java.lang.String,
* org.springframework.beans.factory.ObjectFactory)
*/
public Object get(String name, ObjectFactory<?> objectFactory) {
if (createNewScope) {
beans.clear();
// reset the flag back
createNewScope = false;
}
Object bean = beans.get(name);
// if a new object is requested or none exists under the current
// name, create one
if (bean == null) {
beans.put(name, objectFactory.getObject());
}
return beans.get(name);
}
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.config.Scope#getConversationId()
*/
public String getConversationId() {
return null;
}
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.config.Scope#registerDestructionCallback(java.lang.String,
* java.lang.Runnable)
*/
public void registerDestructionCallback(String name, Runnable callback) {
// do nothing
}
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.config.Scope#remove(java.lang.String)
*/
public Object remove(String name) {
return beans.remove(name);
}
public Object resolveContextualObject(String key) {
// TODO Auto-generated method stub
return null;
}
}

View File

@@ -0,0 +1,17 @@
<?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
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"
xmlns:context="http://www.springframework.org/schema/context">
<context:annotation-config/>
<bean class="org.springframework.context.annotation.support.ConfigurationClassPostProcessor"/>
<bean class="org.springframework.context.annotation.configuration.AutowiredConfigurationTests$ValueConfig"/>
<!--
<context:component-scan base-package="test.basic.value"/>
-->
</beans>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"
xmlns:context="http://www.springframework.org/schema/context">
<aop:aspectj-autoproxy proxy-target-class="true"/>
</beans>

View File

@@ -0,0 +1,26 @@
/*
* Copyright 2002-2009 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.
*/
/**
* Integration tests for {@link org.springframework.context.annotation.Configuration}
* class processing.
*
* @author Chris Beams
* @see org.springframework.context.annotation.Configuration
* @see org.springframework.context.annotation.Bean
* @see org.springframework.context.annotation.support.ConfigurationClassPostProcessor
*/
package org.springframework.context.annotation.configuration;

View File

@@ -0,0 +1,127 @@
/*
* Copyright 2002-2009 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.support;
import static org.junit.Assert.*;
import org.junit.Test;
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.support.ConfigurationParser;
import test.beans.TestBean;
/**
* TCK-style unit tests for handling circular use of the {@link Import} annotation. Explore
* subclass hierarchy for specific concrete implementations.
*
* @author Chris Beams
*/
public abstract class AbstractCircularImportDetectionTests {
protected abstract ConfigurationParser newParser();
protected abstract String loadAsConfigurationSource(Class<?> clazz) throws Exception;
@Test
public void simpleCircularImportIsDetected() throws Exception {
boolean threw = false;
try {
newParser().parse(loadAsConfigurationSource(A.class), null);
} catch (BeanDefinitionParsingException ex) {
assertTrue("Wrong message. Got: " + ex.getMessage(),
ex.getMessage().contains(
"Illegal attempt by @Configuration class 'AbstractCircularImportDetectionTests.B' " +
"to import class 'AbstractCircularImportDetectionTests.A'"));
threw = true;
}
assertTrue(threw);
}
@Test
public void complexCircularImportIsDetected() throws Exception {
boolean threw = false;
try {
newParser().parse(loadAsConfigurationSource(X.class), null);
} catch (BeanDefinitionParsingException ex) {
assertTrue("Wrong message. Got: " + ex.getMessage(),
ex.getMessage().contains(
"Illegal attempt by @Configuration class 'AbstractCircularImportDetectionTests.Z2' " +
"to import class 'AbstractCircularImportDetectionTests.Z'"));
threw = true;
}
assertTrue(threw);
}
@Import(B.class)
static class A {
@Bean
TestBean b1() {
return new TestBean();
}
}
@Import(A.class)
static class B {
@Bean
TestBean b2() {
return new TestBean();
}
}
@Import( { Y.class, Z.class })
class X {
@Bean
TestBean x() {
return new TestBean();
}
}
class Y {
@Bean
TestBean y() {
return new TestBean();
}
}
@Import( { Z1.class, Z2.class })
class Z {
@Bean
TestBean z() {
return new TestBean();
}
}
class Z1 {
@Bean
TestBean z1() {
return new TestBean();
}
}
@Import(Z.class)
class Z2 {
@Bean
TestBean z2() {
return new TestBean();
}
}
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright 2002-2009 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.support;
import org.springframework.beans.factory.parsing.FailFastProblemReporter;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.support.ConfigurationParser;
import org.springframework.util.ClassUtils;
/**
* Unit test proving that ASM-based {@link ConfigurationParser} correctly detects circular use of
* the {@link Import @Import} annotation.
*
* <p>While this test is the only subclass of {@link AbstractCircularImportDetectionTests}, the
* hierarchy remains in place in case a JDT-based ConfigurationParser implementation needs to be
* developed.
*
* @author Chris Beams
*/
public class AsmCircularImportDetectionTests extends AbstractCircularImportDetectionTests {
@Override
protected ConfigurationParser newParser() {
return new ConfigurationParser(new FailFastProblemReporter(), ClassUtils.getDefaultClassLoader());
}
@Override
protected String loadAsConfigurationSource(Class<?> clazz) throws Exception {
return clazz.getName();
}
}

View File

@@ -0,0 +1,182 @@
/*
* Copyright 2002-2009 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.support;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import static org.springframework.context.annotation.ScopedProxyMode.*;
import static org.springframework.context.annotation.StandardScopes.*;
import static org.springframework.context.annotation.support.MutableAnnotationUtils.*;
import java.lang.reflect.Modifier;
import org.junit.Test;
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
import org.springframework.beans.factory.parsing.FailFastProblemReporter;
import org.springframework.beans.factory.parsing.Location;
import org.springframework.beans.factory.parsing.ProblemReporter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.support.BeanMethod;
import org.springframework.context.annotation.support.ConfigurationClass;
import org.springframework.context.annotation.support.ModelClass;
import org.springframework.core.io.ClassPathResource;
/**
* Unit tests for {@link BeanMethod}.
*
* @author Chris Beams
*/
public class BeanMethodTests {
private ProblemReporter problemReporter = new FailFastProblemReporter();
private String beanName = "foo";
private Bean beanAnno = createMutableAnnotation(Bean.class);
private ModelClass returnType = new ModelClass("FooType");
private ConfigurationClass declaringClass = new ConfigurationClass();
{ declaringClass.setName("test.Config"); }
@Test
public void testWellFormedMethod() {
BeanMethod beanMethod = new BeanMethod(beanName, 0, returnType, beanAnno);
assertThat(beanMethod.getName(), sameInstance(beanName));
assertThat(beanMethod.getModifiers(), equalTo(0));
assertThat(beanMethod.getReturnType(), sameInstance(returnType));
assertThat(beanMethod.getAnnotation(Bean.class), sameInstance(beanAnno));
assertThat(beanMethod.getAnnotation(Override.class), nullValue());
assertThat(beanMethod.getRequiredAnnotation(Bean.class), sameInstance(beanAnno));
try {
beanMethod.getRequiredAnnotation(Override.class);
fail("expected IllegalArgumentException ex");
} catch (IllegalArgumentException ex) { /* expected */ }
// must call setDeclaringClass() before calling getLocation()
try {
beanMethod.getLocation();
fail("expected IllegalStateException ex");
} catch (IllegalStateException ex) { /* expected */ }
beanMethod.setDeclaringClass(declaringClass);
assertThat(beanMethod.getDeclaringClass(), sameInstance(declaringClass));
beanMethod.setSource(12); // indicating a line number
assertEquals(beanMethod.getSource(), 12);
Location location = beanMethod.getLocation();
assertEquals(location.getResource(), new ClassPathResource("test/Config"));
assertEquals(location.getSource(), 12);
// should validate without throwing as this is a well-formed method
beanMethod.validate(problemReporter);
}
@Test
public void finalMethodsAreIllegal() {
BeanMethod beanMethod = new BeanMethod(beanName, Modifier.FINAL, returnType, beanAnno);
beanMethod.setDeclaringClass(declaringClass);
try {
beanMethod.validate(problemReporter);
fail("should have failed due to final bean method");
} catch (BeanDefinitionParsingException ex) {
assertTrue(ex.getMessage().contains("remove the final modifier"));
}
}
@Test
public void privateMethodsAreIllegal() {
BeanMethod beanMethod = new BeanMethod(beanName, Modifier.PRIVATE, returnType, beanAnno);
beanMethod.setDeclaringClass(declaringClass);
try {
beanMethod.validate(problemReporter);
fail("should have failed due to private bean method");
} catch (BeanDefinitionParsingException ex) {
assertTrue(ex.getMessage().contains("increase the method's visibility"));
}
}
@Test
public void singletonInterfaceScopedProxiesAreIllegal() {
Scope scope = SingletonInterfaceProxy.class.getAnnotation(Scope.class);
BeanMethod beanMethod = new BeanMethod(beanName, 0, returnType, beanAnno, scope);
beanMethod.setDeclaringClass(declaringClass);
try {
beanMethod.validate(problemReporter);
fail("should have failed due to singleton with scoped proxy");
} catch (Exception ex) {
assertTrue(ex.getMessage().contains("cannot be created for singleton/prototype beans"));
}
}
@Test
public void singletonTargetClassScopedProxiesAreIllegal() {
Scope scope = SingletonTargetClassProxy.class.getAnnotation(Scope.class);
BeanMethod beanMethod = new BeanMethod(beanName, 0, returnType, beanAnno, scope);
beanMethod.setDeclaringClass(declaringClass);
try {
beanMethod.validate(problemReporter);
fail("should have failed due to singleton with scoped proxy");
} catch (Exception ex) {
assertTrue(ex.getMessage().contains("cannot be created for singleton/prototype beans"));
}
}
@Test
public void singletonsSansProxyAreLegal() {
Scope scope = SingletonNoProxy.class.getAnnotation(Scope.class);
BeanMethod beanMethod = new BeanMethod(beanName, 0, returnType, beanAnno, scope);
beanMethod.setDeclaringClass(declaringClass);
beanMethod.validate(problemReporter); // should validate without problems - it's legal
}
@Test
public void prototypeInterfaceScopedProxiesAreIllegal() {
Scope scope = PrototypeInterfaceProxy.class.getAnnotation(Scope.class);
BeanMethod beanMethod = new BeanMethod(beanName, 0, returnType, beanAnno, scope);
beanMethod.setDeclaringClass(declaringClass);
try {
beanMethod.validate(problemReporter);
fail("should have failed due to prototype with scoped proxy");
} catch (Exception ex) {
assertTrue(ex.getMessage().contains("cannot be created for singleton/prototype beans"));
}
}
@Test
public void sessionInterfaceScopedProxiesAreLegal() {
Scope scope = SessionInterfaceProxy.class.getAnnotation(Scope.class);
BeanMethod beanMethod = new BeanMethod(beanName, 0, returnType, beanAnno, scope);
beanMethod.setDeclaringClass(declaringClass);
beanMethod.validate(problemReporter); // should validate without problems - it's legal
}
@Scope(value=SINGLETON, proxyMode=INTERFACES)
private class SingletonInterfaceProxy { }
@Scope(value=SINGLETON, proxyMode=TARGET_CLASS)
private class SingletonTargetClassProxy { }
@Scope(value=SINGLETON, proxyMode=NO)
private class SingletonNoProxy { }
@Scope(value=PROTOTYPE, proxyMode=INTERFACES)
private class PrototypeInterfaceProxy { }
@Scope(value=SESSION, proxyMode=INTERFACES)
private class SessionInterfaceProxy { }
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright 2002-2009 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.support;
import static java.lang.String.*;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import org.junit.Test;
import org.springframework.context.annotation.support.ConfigurationClass;
import org.springframework.context.annotation.support.ConfigurationModel;
/**
* Unit tests for {@link ConfigurationModel}.
*
* @author Chris Beams
*/
public class ConfigurationModelTests {
@Test
public void testToString() {
ConfigurationModel model = new ConfigurationModel();
assertThat(model.toString(), equalTo(
"ConfigurationModel containing @Configuration classes: []"));
ConfigurationClass config1 = new ConfigurationClass();
config1.setName("test.Config1");
model.add(config1);
assertThat(model.toString(), equalTo(format(
"ConfigurationModel containing @Configuration classes: [%s]", config1)));
}
}

View File

@@ -0,0 +1,143 @@
/*
* Copyright 2002-2009 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.support;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.*;
import java.lang.reflect.Field;
import java.util.Vector;
import org.junit.Test;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.support.ConfigurationClassPostProcessor;
import org.springframework.util.ClassUtils;
/**
* Unit tests for {@link ConfigurationClassPostProcessor}.
*
* @author Chris Beams
*/
public class ConfigurationPostProcessorTests {
private static final String ORIG_CGLIB_TEST_CLASS = ConfigurationClassPostProcessor.CGLIB_TEST_CLASS;
private static final String BOGUS_CGLIB_TEST_CLASS = "a.bogus.class";
/**
* CGLIB is an optional dependency for Spring. If users attempt
* to use {@link Configuration} classes, they'll need it on the classpath;
* if Configuration classes are present in the bean factory and CGLIB
* is not present, an instructive exception should be thrown.
*/
@Test
public void testFailFastIfCglibNotPresent() {
@Configuration class Config { }
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
factory.registerBeanDefinition("config", rootBeanDefinition(Config.class).getBeanDefinition());
ConfigurationClassPostProcessor cpp = new ConfigurationClassPostProcessor();
// temporarily set the cglib test class to something bogus
ConfigurationClassPostProcessor.CGLIB_TEST_CLASS = BOGUS_CGLIB_TEST_CLASS;
try {
cpp.postProcessBeanFactory(factory);
} catch (RuntimeException ex) {
assertTrue(ex.getMessage().contains("CGLIB is required to process @Configuration classes"));
} finally {
ConfigurationClassPostProcessor.CGLIB_TEST_CLASS = ORIG_CGLIB_TEST_CLASS;
}
}
/**
* In order to keep Spring's footprint as small as possible, CGLIB must
* not be required on the classpath unless the user is taking advantage
* of {@link Configuration} classes.
*
* This test will fail if any CGLIB classes are classloaded before the call
* to {@link ConfigurationClassPostProcessor#enhanceConfigurationClasses}
*/
@Test
public void testCglibClassesAreLoadedJustInTimeForEnhancement() throws Exception {
ClassLoader classLoader = ClassUtils.getDefaultClassLoader();
Field classesField = ClassLoader.class.getDeclaredField("classes");
classesField.setAccessible(true);
// first, remove any CGLIB classes that may have been loaded by other tests
@SuppressWarnings("unchecked")
Vector<Class<?>> classes = (Vector<Class<?>>) classesField.get(classLoader);
Vector<Class<?>> cglibClassesAlreadyLoaded = new Vector<Class<?>>();
for(Class<?> loadedClass : classes)
if(loadedClass.getName().startsWith("net.sf.cglib"))
cglibClassesAlreadyLoaded.add(loadedClass);
for(Class<?> cglibClass : cglibClassesAlreadyLoaded)
classes.remove(cglibClass);
// now, execute a scenario where everything except enhancement occurs
// -- no CGLIB classes should get loaded!
testFailFastIfCglibNotPresent();
// test to ensure that indeed no CGLIB classes have been loaded
for(Class<?> loadedClass : classes)
if(loadedClass.getName().startsWith("net.sf.cglib"))
fail("CGLIB class should not have been eagerly loaded: " + loadedClass.getName());
}
/**
* Enhanced {@link Configuration} classes are only necessary for respecting
* certain bean semantics, like singleton-scoping, scoped proxies, etc.
*
* Technically, {@link ConfigurationClassPostProcessor} could fail to enhance the
* registered Configuration classes and many use cases would still work.
* Certain cases, however, like inter-bean singleton references would not.
* We test for such a case below, and in doing so prove that enhancement is
* working.
*/
@Test
public void testEnhancementIsPresentBecauseSingletonSemanticsAreRespected() {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
beanFactory.registerBeanDefinition("config",
rootBeanDefinition(SingletonBeanConfig.class).getBeanDefinition());
new ConfigurationClassPostProcessor().postProcessBeanFactory(beanFactory);
Foo foo = (Foo) beanFactory.getBean("foo");
Bar bar = (Bar) beanFactory.getBean("bar");
assertThat(foo, sameInstance(bar.foo));
}
@Configuration
static class SingletonBeanConfig {
public @Bean Foo foo() {
return new Foo();
}
public @Bean Bar bar() {
return new Bar(foo());
}
}
static class Foo { }
static class Bar {
final Foo foo;
public Bar(Foo foo) { this.foo = foo; }
}
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright 2002-2009 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.support;
import static org.junit.Assert.*;
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.*;
import org.junit.Test;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.support.ConfigurationClassPostProcessor;
/**
* Unit tests covering cases where a user defines an invalid Configuration
* class, e.g.: forgets to annotate with {@link Configuration} or declares
* a Configuration class as final.
*
* @author Chris Beams
*/
public class InvalidConfigurationClassDefinitionTests {
@Test
public void configurationClassesMayNotBeFinal() {
@Configuration
final class Config { }
BeanDefinition configBeanDef = rootBeanDefinition(Config.class).getBeanDefinition();
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
beanFactory.registerBeanDefinition("config", configBeanDef);
try {
new ConfigurationClassPostProcessor().postProcessBeanFactory(beanFactory);
fail("expected exception");
} catch (BeanDefinitionParsingException ex) {
assertTrue(ex.getMessage(), ex.getMessage().contains("Remove the final modifier"));
}
}
}

View File

@@ -0,0 +1,23 @@
/*
* Copyright 2002-2009 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.
*/
/**
* Unit tests for support classes related to
* {@link org.springframework.context.annotation.Configuration} class processing.
*
* @author Chris Beams
*/
package org.springframework.context.annotation.support;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 the original author or authors.
* Copyright 2002-2009 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.
@@ -49,7 +49,7 @@ import org.springframework.util.ObjectUtils;
* @author Chris Beams
*/
public final class ClassPathXmlApplicationContextTests {
private static final String PATH = "/org/springframework/context/support/";
private static final String RESOURCE_CONTEXT = PATH + "ClassPathXmlApplicationContextTests-resource.xml";
private static final String CONTEXT_WILDCARD = PATH + "test/context*.xml";

View File

@@ -0,0 +1,40 @@
/*
* Copyright 2002-2008 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 test.beans;
import org.springframework.core.enums.ShortCodedLabeledEnum;
/**
* TODO: JAVADOC
*
* @author Rob Harrop
*/
@SuppressWarnings("serial")
public class Colour extends ShortCodedLabeledEnum {
public static final Colour RED = new Colour(0, "RED");
public static final Colour BLUE = new Colour(1, "BLUE");
public static final Colour GREEN = new Colour(2, "GREEN");
public static final Colour PURPLE = new Colour(3, "PURPLE");
private Colour(int code, String label) {
super(code, label);
}
}

View File

@@ -0,0 +1,89 @@
/*
* Copyright 2002-2008 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 test.beans;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.config.Scope;
/**
* Simple scope implementation which creates object based on a flag.
*
* @author Costin Leau
* @author Chris Beams
*/
public class CustomScope implements Scope {
public boolean createNewScope = true;
private Map<String, Object> beans = new HashMap<String, Object>();
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.config.Scope#get(java.lang.String,
* org.springframework.beans.factory.ObjectFactory)
*/
public Object get(String name, ObjectFactory<?> objectFactory) {
if (createNewScope) {
beans.clear();
// reset the flag back
createNewScope = false;
}
Object bean = beans.get(name);
// if a new object is requested or none exists under the current
// name, create one
if (bean == null) {
beans.put(name, objectFactory.getObject());
}
return beans.get(name);
}
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.config.Scope#getConversationId()
*/
public String getConversationId() {
return null;
}
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.config.Scope#registerDestructionCallback(java.lang.String,
* java.lang.Runnable)
*/
public void registerDestructionCallback(String name, Runnable callback) {
// do nothing
}
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.config.Scope#remove(java.lang.String)
*/
public Object remove(String name) {
return beans.remove(name);
}
public Object resolveContextualObject(String key) {
// TODO Auto-generated method stub
return null;
}
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright 2002-2008 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 test.beans;
/** TODO: JAVADOC */
public class DependsOnTestBean {
public TestBean tb;
private int state;
public void setTestBean(TestBean tb) {
this.tb = tb;
}
public int getState() {
return state;
}
public TestBean getTestBean() {
return tb;
}
}

View File

@@ -0,0 +1,24 @@
/*
* Copyright 2002-2008 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 test.beans;
/** TODO: JAVADOC */
public interface INestedTestBean {
String getCompany();
}

View File

@@ -0,0 +1,24 @@
/*
* Copyright 2002-2008 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 test.beans;
/** TODO: JAVADOC */
public interface IOther {
void absquatulate();
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright 2002-2008 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 test.beans;
import java.io.IOException;
/**
* Interface used for test beans. Two methods are the same as on Person, but if this extends
* person it breaks quite a few tests
*
* @author Rod Johnson
*/
public interface ITestBean {
int getAge();
void setAge(int age);
String getName();
void setName(String name);
ITestBean getSpouse();
void setSpouse(ITestBean spouse);
/**
* t null no error.
*/
void exceptional(Throwable t) throws Throwable;
Object returnsThis();
INestedTestBean getDoctor();
INestedTestBean getLawyer();
IndexedTestBean getNestedIndexedBean();
/**
* Increment the age by one.
*
* @return the previous age
*/
int haveBirthday();
void unreliableFileOperation() throws IOException;
}

View File

@@ -0,0 +1,145 @@
/*
* Copyright 2002-2008 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 test.beans;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeSet;
/**
* TODO: JAVADOC
*
* @author Juergen Hoeller
* @since 11.11.2003
*/
public class IndexedTestBean {
private TestBean[] array;
private Collection<TestBean> collection;
private List<TestBean> list;
private Set<TestBean> set;
private SortedSet<TestBean> sortedSet;
private Map<String, Object> map;
private SortedMap<String, TestBean> sortedMap;
public IndexedTestBean() {
this(true);
}
public IndexedTestBean(boolean populate) {
if (populate) {
populate();
}
}
public void populate() {
TestBean tb0 = new TestBean("name0", 0);
TestBean tb1 = new TestBean("name1", 0);
TestBean tb2 = new TestBean("name2", 0);
TestBean tb3 = new TestBean("name3", 0);
TestBean tb4 = new TestBean("name4", 0);
TestBean tb5 = new TestBean("name5", 0);
TestBean tb6 = new TestBean("name6", 0);
TestBean tb7 = new TestBean("name7", 0);
TestBean tbX = new TestBean("nameX", 0);
TestBean tbY = new TestBean("nameY", 0);
this.array = new TestBean[] { tb0, tb1 };
this.list = new ArrayList<TestBean>();
this.list.add(tb2);
this.list.add(tb3);
this.set = new TreeSet<TestBean>();
this.set.add(tb6);
this.set.add(tb7);
this.map = new HashMap<String, Object>();
this.map.put("key1", tb4);
this.map.put("key2", tb5);
this.map.put("key.3", tb5);
List<TestBean> list = new ArrayList<TestBean>();
list.add(tbX);
list.add(tbY);
this.map.put("key4", list);
}
public TestBean[] getArray() {
return array;
}
public void setArray(TestBean[] array) {
this.array = array;
}
public Collection<?> getCollection() {
return collection;
}
public void setCollection(Collection<TestBean> collection) {
this.collection = collection;
}
public List<TestBean> getList() {
return list;
}
public void setList(List<TestBean> list) {
this.list = list;
}
public Set<TestBean> getSet() {
return set;
}
public void setSet(Set<TestBean> set) {
this.set = set;
}
public SortedSet<TestBean> getSortedSet() {
return sortedSet;
}
public void setSortedSet(SortedSet<TestBean> sortedSet) {
this.sortedSet = sortedSet;
}
public Map<String, Object> getMap() {
return map;
}
public void setMap(Map<String, Object> map) {
this.map = map;
}
public SortedMap<String, TestBean> getSortedMap() {
return sortedMap;
}
public void setSortedMap(SortedMap<String, TestBean> sortedMap) {
this.sortedMap = sortedMap;
}
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright 2002-2008 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 test.beans;
/**
* Simple nested test bean used for testing bean factories, AOP framework etc.
*
* @author Trevor D. Cook
* @since 30.09.2003
*/
public class NestedTestBean implements INestedTestBean {
private String company = "";
public NestedTestBean() {
}
public NestedTestBean(String company) {
setCompany(company);
}
public void setCompany(String company) {
this.company = ((company != null) ? company : "");
}
public String getCompany() {
return company;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof NestedTestBean)) {
return false;
}
NestedTestBean ntb = (NestedTestBean) obj;
return this.company.equals(ntb.company);
}
@Override
public int hashCode() {
return this.company.hashCode();
}
@Override
public String toString() {
return "NestedTestBean: " + this.company;
}
}

View File

@@ -0,0 +1,419 @@
/*
* Copyright 2002-2008 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 test.beans;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.util.ObjectUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
/**
* Simple test bean used for testing bean factories, AOP framework etc.
*
* @author Rod Johnson
* @since 15 April 2001
*/
public class TestBean implements BeanNameAware, BeanFactoryAware, ITestBean, IOther, Comparable<Object> {
private String beanName;
private String country;
private BeanFactory beanFactory;
private boolean postProcessed;
private String name;
private String sex;
private int age;
private boolean jedi;
private ITestBean spouse;
private String touchy;
private String[] stringArray;
private Integer[] someIntegerArray;
private Date date = new Date();
private Float myFloat = new Float(0.0);
private Collection<?> friends = new LinkedList<Object>();
private Set<?> someSet = new HashSet<Object>();
private Map<?, ?> someMap = new HashMap<Object, Object>();
private List<?> someList = new ArrayList<Object>();
private Properties someProperties = new Properties();
private INestedTestBean doctor = new NestedTestBean();
private INestedTestBean lawyer = new NestedTestBean();
private IndexedTestBean nestedIndexedBean;
private boolean destroyed;
private Number someNumber;
private Colour favouriteColour;
private Boolean someBoolean;
private List<?> otherColours;
private List<?> pets;
public TestBean() {
}
public TestBean(String name) {
this.name = name;
}
public TestBean(ITestBean spouse) {
this.spouse = spouse;
}
public TestBean(String name, int age) {
this.name = name;
this.age = age;
}
public TestBean(ITestBean spouse, Properties someProperties) {
this.spouse = spouse;
this.someProperties = someProperties;
}
public void setBeanName(String beanName) {
this.beanName = beanName;
}
public String getBeanName() {
return beanName;
}
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
public BeanFactory getBeanFactory() {
return beanFactory;
}
public void setPostProcessed(boolean postProcessed) {
this.postProcessed = postProcessed;
}
public boolean isPostProcessed() {
return postProcessed;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public boolean isJedi() {
return jedi;
}
public void setJedi(boolean jedi) {
this.jedi = jedi;
}
public ITestBean getSpouse() {
return spouse;
}
public void setSpouse(ITestBean spouse) {
this.spouse = spouse;
}
public String getTouchy() {
return touchy;
}
public void setTouchy(String touchy) throws Exception {
if (touchy.indexOf('.') != -1) {
throw new Exception("Can't contain a .");
}
if (touchy.indexOf(',') != -1) {
throw new NumberFormatException("Number format exception: contains a ,");
}
this.touchy = touchy;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String[] getStringArray() {
return stringArray;
}
public void setStringArray(String[] stringArray) {
this.stringArray = stringArray;
}
public Integer[] getSomeIntegerArray() {
return someIntegerArray;
}
public void setSomeIntegerArray(Integer[] someIntegerArray) {
this.someIntegerArray = someIntegerArray;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public Float getMyFloat() {
return myFloat;
}
public void setMyFloat(Float myFloat) {
this.myFloat = myFloat;
}
public Collection<?> getFriends() {
return friends;
}
public void setFriends(Collection<?> friends) {
this.friends = friends;
}
public Set<?> getSomeSet() {
return someSet;
}
public void setSomeSet(Set<?> someSet) {
this.someSet = someSet;
}
public Map<?, ?> getSomeMap() {
return someMap;
}
public void setSomeMap(Map<?, ?> someMap) {
this.someMap = someMap;
}
public List<?> getSomeList() {
return someList;
}
public void setSomeList(List<?> someList) {
this.someList = someList;
}
public Properties getSomeProperties() {
return someProperties;
}
public void setSomeProperties(Properties someProperties) {
this.someProperties = someProperties;
}
public INestedTestBean getDoctor() {
return doctor;
}
public INestedTestBean getLawyer() {
return lawyer;
}
public void setDoctor(INestedTestBean bean) {
doctor = bean;
}
public void setLawyer(INestedTestBean bean) {
lawyer = bean;
}
public Number getSomeNumber() {
return someNumber;
}
public void setSomeNumber(Number someNumber) {
this.someNumber = someNumber;
}
public Colour getFavouriteColour() {
return favouriteColour;
}
public void setFavouriteColour(Colour favouriteColour) {
this.favouriteColour = favouriteColour;
}
public Boolean getSomeBoolean() {
return someBoolean;
}
public void setSomeBoolean(Boolean someBoolean) {
this.someBoolean = someBoolean;
}
public IndexedTestBean getNestedIndexedBean() {
return nestedIndexedBean;
}
public void setNestedIndexedBean(IndexedTestBean nestedIndexedBean) {
this.nestedIndexedBean = nestedIndexedBean;
}
public List<?> getOtherColours() {
return otherColours;
}
public void setOtherColours(List<?> otherColours) {
this.otherColours = otherColours;
}
public List<?> getPets() {
return pets;
}
public void setPets(List<?> pets) {
this.pets = pets;
}
/**
* @see ITestBean#exceptional(Throwable)
*/
public void exceptional(Throwable t) throws Throwable {
if (t != null) {
throw t;
}
}
public void unreliableFileOperation() throws IOException {
throw new IOException();
}
/**
* @see ITestBean#returnsThis()
*/
public Object returnsThis() {
return this;
}
/**
* @see IOther#absquatulate()
*/
public void absquatulate() {
}
public int haveBirthday() {
return age++;
}
public void destroy() {
this.destroyed = true;
}
public boolean wasDestroyed() {
return destroyed;
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if ((other == null) || !(other instanceof TestBean)) {
return false;
}
TestBean tb2 = (TestBean) other;
return (ObjectUtils.nullSafeEquals(this.name, tb2.name) && (this.age == tb2.age));
}
@Override
public int hashCode() {
return this.age;
}
public int compareTo(Object other) {
if ((this.name != null) && (other instanceof TestBean)) {
return this.name.compareTo(((TestBean) other).getName());
}
return 1;
}
@Override
public String toString() {
String s = "name=" + name + "; age=" + age + "; touchy=" + touchy;
s += "; spouse={" + ((spouse != null) ? spouse.getName() : null) + "}";
return s;
}
}