/* * 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.beans.factory.xml; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.StringWriter; import java.lang.reflect.Method; import java.net.URL; import java.util.Map; import javax.servlet.ServletException; import junit.framework.AssertionFailedError; import junit.framework.TestCase; import org.apache.commons.logging.LogFactory; import org.xml.sax.InputSource; import org.springframework.aop.framework.ProxyFactory; import org.springframework.aop.support.AopUtils; import org.springframework.beans.BeansException; import org.springframework.beans.DerivedTestBean; import org.springframework.beans.FatalBeanException; import org.springframework.beans.ITestBean; import org.springframework.beans.IndexedTestBean; import org.springframework.beans.MutablePropertyValues; import org.springframework.beans.ResourceTestBean; import org.springframework.beans.TestBean; import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.BeanCurrentlyInCreationException; import org.springframework.beans.factory.BeanDefinitionStoreException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanIsAbstractException; import org.springframework.beans.factory.CannotLoadBeanClassException; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.DummyFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.UnsatisfiedDependencyException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.MethodReplacer; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.Resource; import org.springframework.core.io.UrlResource; import org.springframework.core.io.support.EncodedResource; import org.springframework.util.FileCopyUtils; import org.springframework.util.SerializationTestUtils; import org.springframework.util.StopWatch; /** * Miscellaneous tests for XML bean definitions. * * @author Juergen Hoeller * @author Rod Johnson * @author Rick Evans */ public class XmlBeanFactoryTests extends TestCase { /* * http://opensource.atlassian.com/projects/spring/browse/SPR-2368 */ public void testCollectionsReferredToAsRefLocals() throws Exception { XmlBeanFactory factory = new XmlBeanFactory( new ClassPathResource("local-collections-using-XSD.xml", getClass())); factory.preInstantiateSingletons(); } public void testRefToSeparatePrototypeInstances() throws Exception { DefaultListableBeanFactory xbf = new DefaultListableBeanFactory(); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf); reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_NONE); reader.loadBeanDefinitions(new ClassPathResource("reftypes.xml", getClass())); TestBean emma = (TestBean) xbf.getBean("emma"); TestBean georgia = (TestBean) xbf.getBean("georgia"); ITestBean emmasJenks = emma.getSpouse(); ITestBean georgiasJenks = georgia.getSpouse(); assertTrue("Emma and georgia think they have a different boyfriend", emmasJenks != georgiasJenks); assertTrue("Emmas jenks has right name", emmasJenks.getName().equals("Andrew")); assertTrue("Emmas doesn't equal new ref", emmasJenks != xbf.getBean("jenks")); assertTrue("Georgias jenks has right name", emmasJenks.getName().equals("Andrew")); assertTrue("They are object equal", emmasJenks.equals(georgiasJenks)); assertTrue("They object equal direct ref", emmasJenks.equals(xbf.getBean("jenks"))); } public void testRefToSingleton() throws Exception { DefaultListableBeanFactory xbf = new DefaultListableBeanFactory(); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf); reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_NONE); Resource resource = new ClassPathResource("reftypes.xml", getClass()); reader.loadBeanDefinitions(new EncodedResource(resource, "ISO-8859-1")); TestBean jen = (TestBean) xbf.getBean("jenny"); TestBean dave = (TestBean) xbf.getBean("david"); TestBean jenks = (TestBean) xbf.getBean("jenks"); ITestBean davesJen = dave.getSpouse(); ITestBean jenksJen = jenks.getSpouse(); assertTrue("1 jen instance", davesJen == jenksJen); assertTrue("1 jen instance", davesJen == jen); } public void testInnerBeans() throws IOException { DefaultListableBeanFactory xbf = new DefaultListableBeanFactory(); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf); reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_NONE); InputStream inputStream = getClass().getResourceAsStream("reftypes.xml"); try { reader.loadBeanDefinitions(new InputSource(inputStream)); } finally { inputStream.close(); } // Let's create the outer bean named "innerBean", // to check whether it doesn't create any conflicts // with the actual inner beans named "innerBean". xbf.getBean("innerBean"); TestBean hasInnerBeans = (TestBean) xbf.getBean("hasInnerBeans"); assertEquals(5, hasInnerBeans.getAge()); TestBean inner1 = (TestBean) hasInnerBeans.getSpouse(); assertNotNull(inner1); assertEquals("innerBean#1", inner1.getBeanName()); assertEquals("inner1", inner1.getName()); assertEquals(6, inner1.getAge()); assertNotNull(hasInnerBeans.getFriends()); Object[] friends = hasInnerBeans.getFriends().toArray(); assertEquals(3, friends.length); DerivedTestBean inner2 = (DerivedTestBean) friends[0]; assertEquals("inner2", inner2.getName()); assertTrue(inner2.getBeanName().startsWith(DerivedTestBean.class.getName())); assertFalse(xbf.containsBean("innerBean#1")); assertNotNull(inner2); assertEquals(7, inner2.getAge()); TestBean innerFactory = (TestBean) friends[1]; assertEquals(DummyFactory.SINGLETON_NAME, innerFactory.getName()); TestBean inner5 = (TestBean) friends[2]; assertEquals("innerBean#2", inner5.getBeanName()); assertNotNull(hasInnerBeans.getSomeMap()); assertEquals(2, hasInnerBeans.getSomeMap().size()); TestBean inner3 = (TestBean) hasInnerBeans.getSomeMap().get("someKey"); assertEquals("Jenny", inner3.getName()); assertEquals(30, inner3.getAge()); TestBean inner4 = (TestBean) hasInnerBeans.getSomeMap().get("someOtherKey"); assertEquals("inner4", inner4.getName()); assertEquals(9, inner4.getAge()); TestBean hasInnerBeansForConstructor = (TestBean) xbf.getBean("hasInnerBeansForConstructor"); TestBean innerForConstructor = (TestBean) hasInnerBeansForConstructor.getSpouse(); assertNotNull(innerForConstructor); assertEquals("innerBean#3", innerForConstructor.getBeanName()); assertEquals("inner1", innerForConstructor.getName()); assertEquals(6, innerForConstructor.getAge()); xbf.destroySingletons(); assertTrue(inner1.wasDestroyed()); assertTrue(inner2.wasDestroyed()); assertTrue(innerFactory.getName() == null); assertTrue(inner5.wasDestroyed()); } public void testInnerBeansWithoutDestroy() { DefaultListableBeanFactory xbf = new DefaultListableBeanFactory(); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf); reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_NONE); reader.loadBeanDefinitions(new ClassPathResource("reftypes.xml", getClass())); // Let's create the outer bean named "innerBean", // to check whether it doesn't create any conflicts // with the actual inner beans named "innerBean". xbf.getBean("innerBean"); TestBean hasInnerBeans = (TestBean) xbf.getBean("hasInnerBeansWithoutDestroy"); assertEquals(5, hasInnerBeans.getAge()); TestBean inner1 = (TestBean) hasInnerBeans.getSpouse(); assertNotNull(inner1); assertEquals("innerBean", inner1.getBeanName()); assertEquals("inner1", inner1.getName()); assertEquals(6, inner1.getAge()); assertNotNull(hasInnerBeans.getFriends()); Object[] friends = hasInnerBeans.getFriends().toArray(); assertEquals(3, friends.length); DerivedTestBean inner2 = (DerivedTestBean) friends[0]; assertEquals("inner2", inner2.getName()); assertTrue(inner2.getBeanName().startsWith(DerivedTestBean.class.getName())); assertNotNull(inner2); assertEquals(7, inner2.getAge()); TestBean innerFactory = (TestBean) friends[1]; assertEquals(DummyFactory.SINGLETON_NAME, innerFactory.getName()); TestBean inner5 = (TestBean) friends[2]; assertEquals("innerBean", inner5.getBeanName()); } public void testFailsOnInnerBean() { DefaultListableBeanFactory xbf = new DefaultListableBeanFactory(); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf); reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_NONE); reader.loadBeanDefinitions(new ClassPathResource("reftypes.xml", getClass())); try { xbf.getBean("failsOnInnerBean"); } catch (BeanCreationException ex) { // Check whether message contains outer bean name. ex.printStackTrace(); assertTrue(ex.getMessage().indexOf("failsOnInnerBean") != -1); assertTrue(ex.getMessage().indexOf("someMap") != -1); } try { xbf.getBean("failsOnInnerBeanForConstructor"); } catch (BeanCreationException ex) { // Check whether message contains outer bean name. ex.printStackTrace(); assertTrue(ex.getMessage().indexOf("failsOnInnerBeanForConstructor") != -1); assertTrue(ex.getMessage().indexOf("constructor argument") != -1); } } public void testSingletonInheritanceFromParentFactorySingleton() throws Exception { XmlBeanFactory parent = new XmlBeanFactory(new ClassPathResource("parent.xml", getClass())); XmlBeanFactory child = new XmlBeanFactory(new ClassPathResource("child.xml", getClass()), parent); assertEquals(TestBean.class, child.getType("inheritsFromParentFactory")); TestBean inherits = (TestBean) child.getBean("inheritsFromParentFactory"); // Name property value is overridden assertTrue(inherits.getName().equals("override")); // Age property is inherited from bean in parent factory assertTrue(inherits.getAge() == 1); TestBean inherits2 = (TestBean) child.getBean("inheritsFromParentFactory"); assertTrue(inherits2 == inherits); } public void testInheritanceWithDifferentClass() throws Exception { XmlBeanFactory parent = new XmlBeanFactory(new ClassPathResource("parent.xml", getClass())); XmlBeanFactory child = new XmlBeanFactory(new ClassPathResource("child.xml", getClass()), parent); assertEquals(DerivedTestBean.class, child.getType("inheritsWithClass")); DerivedTestBean inherits = (DerivedTestBean) child.getBean("inheritsWithDifferentClass"); // Name property value is overridden assertTrue(inherits.getName().equals("override")); // Age property is inherited from bean in parent factory assertTrue(inherits.getAge() == 1); assertTrue(inherits.wasInitialized()); } public void testInheritanceWithClass() throws Exception { XmlBeanFactory parent = new XmlBeanFactory(new ClassPathResource("parent.xml", getClass())); XmlBeanFactory child = new XmlBeanFactory(new ClassPathResource("child.xml", getClass()), parent); assertEquals(DerivedTestBean.class, child.getType("inheritsWithClass")); DerivedTestBean inherits = (DerivedTestBean) child.getBean("inheritsWithClass"); // Name property value is overridden assertTrue(inherits.getName().equals("override")); // Age property is inherited from bean in parent factory assertTrue(inherits.getAge() == 1); assertTrue(inherits.wasInitialized()); } public void testPrototypeInheritanceFromParentFactoryPrototype() throws Exception { XmlBeanFactory parent = new XmlBeanFactory(new ClassPathResource("parent.xml", getClass())); XmlBeanFactory child = new XmlBeanFactory(new ClassPathResource("child.xml", getClass()), parent); assertEquals(TestBean.class, child.getType("prototypeInheritsFromParentFactoryPrototype")); TestBean inherits = (TestBean) child.getBean("prototypeInheritsFromParentFactoryPrototype"); // Name property value is overridden assertTrue(inherits.getName().equals("prototype-override")); // Age property is inherited from bean in parent factory assertTrue(inherits.getAge() == 2); TestBean inherits2 = (TestBean) child.getBean("prototypeInheritsFromParentFactoryPrototype"); assertFalse(inherits2 == inherits); inherits2.setAge(13); assertTrue(inherits2.getAge() == 13); // Shouldn't have changed first instance assertTrue(inherits.getAge() == 2); } public void testPrototypeInheritanceFromParentFactorySingleton() throws Exception { XmlBeanFactory parent = new XmlBeanFactory(new ClassPathResource("parent.xml", getClass())); XmlBeanFactory child = new XmlBeanFactory(new ClassPathResource("child.xml", getClass()), parent); TestBean inherits = (TestBean) child.getBean("protoypeInheritsFromParentFactorySingleton"); // Name property value is overridden assertTrue(inherits.getName().equals("prototypeOverridesInheritedSingleton")); // Age property is inherited from bean in parent factory assertTrue(inherits.getAge() == 1); TestBean inherits2 = (TestBean) child.getBean("protoypeInheritsFromParentFactorySingleton"); assertFalse(inherits2 == inherits); inherits2.setAge(13); assertTrue(inherits2.getAge() == 13); // Shouldn't have changed first instance assertTrue(inherits.getAge() == 1); } public void testAutowireModeNotInherited() { DefaultListableBeanFactory xbf = new DefaultListableBeanFactory(); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf); reader.loadBeanDefinitions(new ClassPathResource("overrides.xml", getClass())); TestBean david = (TestBean)xbf.getBean("magicDavid"); // the parent bean is autowiring assertNotNull(david.getSpouse()); TestBean derivedDavid = (TestBean)xbf.getBean("magicDavidDerived"); // this fails while it inherits from the child bean assertNull("autowiring not propagated along child relationships", derivedDavid.getSpouse()); } public void testAbstractParentBeans() { XmlBeanFactory parent = new XmlBeanFactory(new ClassPathResource("parent.xml", getClass())); parent.preInstantiateSingletons(); assertTrue(parent.isSingleton("inheritedTestBeanWithoutClass")); // abstract beans should not match Map tbs = parent.getBeansOfType(TestBean.class); assertEquals(2, tbs.size()); assertTrue(tbs.containsKey("inheritedTestBeanPrototype")); assertTrue(tbs.containsKey("inheritedTestBeanSingleton")); // abstract bean should throw exception on creation attempt try { parent.getBean("inheritedTestBeanWithoutClass"); fail("Should have thrown BeanIsAbstractException"); } catch (BeanIsAbstractException ex) { // expected } // non-abstract bean should work, even if it serves as parent assertTrue(parent.getBean("inheritedTestBeanPrototype") instanceof TestBean); } public void testDependenciesMaterializeThis() throws Exception { XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("dependenciesMaterializeThis.xml", getClass())); assertEquals(2, xbf.getBeansOfType(DummyBo.class, true, false).size()); assertEquals(3, xbf.getBeansOfType(DummyBo.class, true, true).size()); assertEquals(3, xbf.getBeansOfType(DummyBo.class, true, false).size()); assertEquals(3, xbf.getBeansOfType(DummyBo.class).size()); assertEquals(2, xbf.getBeansOfType(DummyBoImpl.class, true, true).size()); assertEquals(1, xbf.getBeansOfType(DummyBoImpl.class, false, true).size()); assertEquals(2, xbf.getBeansOfType(DummyBoImpl.class).size()); DummyBoImpl bos = (DummyBoImpl) xbf.getBean("boSingleton"); DummyBoImpl bop = (DummyBoImpl) xbf.getBean("boPrototype"); assertNotSame(bos, bop); assertTrue(bos.dao == bop.dao); } public void testChildOverridesParentBean() throws Exception { XmlBeanFactory parent = new XmlBeanFactory(new ClassPathResource("parent.xml", getClass())); XmlBeanFactory child = new XmlBeanFactory(new ClassPathResource("child.xml", getClass()), parent); TestBean inherits = (TestBean) child.getBean("inheritedTestBean"); // Name property value is overridden assertTrue(inherits.getName().equals("overrideParentBean")); // Age property is inherited from bean in parent factory assertTrue(inherits.getAge() == 1); TestBean inherits2 = (TestBean) child.getBean("inheritedTestBean"); assertTrue(inherits2 == inherits); } /** * Check that a prototype can't inherit from a bogus parent. * If a singleton does this the factory will fail to load. */ public void testBogusParentageFromParentFactory() throws Exception { XmlBeanFactory parent = new XmlBeanFactory(new ClassPathResource("parent.xml", getClass())); XmlBeanFactory child = new XmlBeanFactory(new ClassPathResource("child.xml", getClass()), parent); try { child.getBean("bogusParent", TestBean.class); fail(); } catch (BeanDefinitionStoreException ex) { // check exception message contains the name assertTrue(ex.getMessage().indexOf("bogusParent") != -1); assertTrue(ex.getCause() instanceof NoSuchBeanDefinitionException); } } /** * Note that prototype/singleton distinction is <b>not</b> inherited. * It's possible for a subclass singleton not to return independent * instances even if derived from a prototype */ public void testSingletonInheritsFromParentFactoryPrototype() throws Exception { XmlBeanFactory parent = new XmlBeanFactory(new ClassPathResource("parent.xml", getClass())); XmlBeanFactory child = new XmlBeanFactory(new ClassPathResource("child.xml", getClass()), parent); TestBean inherits = (TestBean) child.getBean("singletonInheritsFromParentFactoryPrototype"); // Name property value is overriden assertTrue(inherits.getName().equals("prototype-override")); // Age property is inherited from bean in parent factory assertTrue(inherits.getAge() == 2); TestBean inherits2 = (TestBean) child.getBean("singletonInheritsFromParentFactoryPrototype"); assertTrue(inherits2 == inherits); } public void testSingletonFromParent() { XmlBeanFactory parent = new XmlBeanFactory(new ClassPathResource("parent.xml", getClass())); TestBean beanFromParent = (TestBean) parent.getBean("inheritedTestBeanSingleton"); XmlBeanFactory child = new XmlBeanFactory(new ClassPathResource("child.xml", getClass()), parent); TestBean beanFromChild = (TestBean) child.getBean("inheritedTestBeanSingleton"); assertTrue("singleton from parent and child is the same", beanFromParent == beanFromChild); } public void testNestedPropertyValue() { XmlBeanFactory parent = new XmlBeanFactory(new ClassPathResource("parent.xml", getClass())); XmlBeanFactory child = new XmlBeanFactory(new ClassPathResource("child.xml", getClass()), parent); IndexedTestBean bean = (IndexedTestBean) child.getBean("indexedTestBean"); assertEquals("name applied correctly", "myname", bean.getArray()[0].getName()); } public void testCircularReferences() { DefaultListableBeanFactory xbf = new DefaultListableBeanFactory(); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf); reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_NONE); reader.loadBeanDefinitions(new ClassPathResource("reftypes.xml", getClass())); TestBean jenny = (TestBean) xbf.getBean("jenny"); TestBean david = (TestBean) xbf.getBean("david"); TestBean ego = (TestBean) xbf.getBean("ego"); TestBean complexInnerEgo = (TestBean) xbf.getBean("complexInnerEgo"); TestBean complexEgo = (TestBean) xbf.getBean("complexEgo"); assertTrue("Correct circular reference", jenny.getSpouse() == david); assertTrue("Correct circular reference", david.getSpouse() == jenny); assertTrue("Correct circular reference", ego.getSpouse() == ego); assertTrue("Correct circular reference", complexInnerEgo.getSpouse().getSpouse() == complexInnerEgo); assertTrue("Correct circular reference", complexEgo.getSpouse().getSpouse() == complexEgo); } public void testCircularReferenceWithFactoryBeanFirst() { DefaultListableBeanFactory xbf = new DefaultListableBeanFactory(); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf); reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_NONE); reader.loadBeanDefinitions(new ClassPathResource("reftypes.xml", getClass())); TestBean egoBridge = (TestBean) xbf.getBean("egoBridge"); TestBean complexEgo = (TestBean) xbf.getBean("complexEgo"); assertTrue("Correct circular reference", complexEgo.getSpouse().getSpouse() == complexEgo); } public void testCircularReferenceWithTwoFactoryBeans() { DefaultListableBeanFactory xbf = new DefaultListableBeanFactory(); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf); reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_NONE); reader.loadBeanDefinitions(new ClassPathResource("reftypes.xml", getClass())); TestBean ego1 = (TestBean) xbf.getBean("ego1"); assertTrue("Correct circular reference", ego1.getSpouse().getSpouse() == ego1); TestBean ego3 = (TestBean) xbf.getBean("ego3"); assertTrue("Correct circular reference", ego3.getSpouse().getSpouse() == ego3); } public void testCircularReferencesWithNotAllowed() { DefaultListableBeanFactory xbf = new DefaultListableBeanFactory(); xbf.setAllowCircularReferences(false); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf); reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_NONE); reader.loadBeanDefinitions(new ClassPathResource("reftypes.xml", getClass())); try { xbf.getBean("jenny"); fail("Should have thrown BeanCreationException"); } catch (BeanCreationException ex) { assertTrue(ex.contains(BeanCurrentlyInCreationException.class)); } } public void testCircularReferencesWithWrapping() { DefaultListableBeanFactory xbf = new DefaultListableBeanFactory(); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf); reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_NONE); reader.loadBeanDefinitions(new ClassPathResource("reftypes.xml", getClass())); xbf.addBeanPostProcessor(new WrappingPostProcessor()); try { xbf.getBean("jenny"); fail("Should have thrown BeanCreationException"); } catch (BeanCreationException ex) { assertTrue(ex.contains(BeanCurrentlyInCreationException.class)); } } public void testCircularReferencesWithWrappingAndRawInjectionAllowed() { DefaultListableBeanFactory xbf = new DefaultListableBeanFactory(); xbf.setAllowRawInjectionDespiteWrapping(true); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf); reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_NONE); reader.loadBeanDefinitions(new ClassPathResource("reftypes.xml", getClass())); xbf.addBeanPostProcessor(new WrappingPostProcessor()); ITestBean jenny = (ITestBean) xbf.getBean("jenny"); ITestBean david = (ITestBean) xbf.getBean("david"); assertTrue(AopUtils.isAopProxy(jenny)); assertTrue(AopUtils.isAopProxy(david)); assertSame(david, jenny.getSpouse()); assertNotSame(jenny, david.getSpouse()); assertEquals("Jenny", david.getSpouse().getName()); assertSame(david, david.getSpouse().getSpouse()); assertTrue(AopUtils.isAopProxy(jenny.getSpouse())); assertTrue(!AopUtils.isAopProxy(david.getSpouse())); } public void testFactoryReferenceCircle() { XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("factoryCircle.xml", getClass())); TestBean tb = (TestBean) xbf.getBean("singletonFactory"); DummyFactory db = (DummyFactory) xbf.getBean("&singletonFactory"); assertTrue(tb == db.getOtherTestBean()); } public void testFactoryReferenceWithDoublePrefix() { XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("factoryCircle.xml", getClass())); DummyFactory db = (DummyFactory) xbf.getBean("&&singletonFactory"); } public void testComplexFactoryReferenceCircle() { XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("complexFactoryCircle.xml", getClass())); xbf.getBean("proxy1"); // check that unused instances from autowiring got removed assertEquals(5, xbf.getSingletonCount()); // properly create the remaining two instances xbf.getBean("proxy2"); assertEquals(7, xbf.getSingletonCount()); } public void testNoSuchFactoryBeanMethod() { try { XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("no-such-factory-method.xml", getClass())); assertNotNull(xbf.getBean("defaultTestBean")); fail("Should not get invalid bean"); } catch (BeanCreationException ex) { // Ok } } public void testInitMethodIsInvoked() throws Exception { XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("initializers.xml", getClass())); DoubleInitializer in = (DoubleInitializer) xbf.getBean("init-method1"); // Initializer should have doubled value assertEquals(14, in.getNum()); } /** * Test that if a custom initializer throws an exception, it's handled correctly */ public void testInitMethodThrowsException() { XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("initializers.xml", getClass())); try { xbf.getBean("init-method2"); fail(); } catch (BeanCreationException ex) { assertTrue(ex.getResourceDescription().indexOf("initializers.xml") != -1); assertEquals("init-method2", ex.getBeanName()); assertTrue(ex.getCause() instanceof ServletException); } } public void testNoSuchInitMethod() throws Exception { XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("initializers.xml", getClass())); try { xbf.getBean("init-method3"); fail(); } catch (FatalBeanException ex) { // check message is helpful assertTrue(ex.getMessage().indexOf("initializers.xml") != -1); assertTrue(ex.getMessage().indexOf("init-method3") != -1); assertTrue(ex.getMessage().indexOf("init") != -1); } } /** * Check that InitializingBean method is called first. */ public void testInitializingBeanAndInitMethod() throws Exception { InitAndIB.constructed = false; XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("initializers.xml", getClass())); assertFalse(InitAndIB.constructed); xbf.preInstantiateSingletons(); assertFalse(InitAndIB.constructed); InitAndIB iib = (InitAndIB) xbf.getBean("init-and-ib"); assertTrue(InitAndIB.constructed); assertTrue(iib.afterPropertiesSetInvoked && iib.initMethodInvoked); assertTrue(!iib.destroyed && !iib.customDestroyed); xbf.destroySingletons(); assertTrue(iib.destroyed && iib.customDestroyed); xbf.destroySingletons(); assertTrue(iib.destroyed && iib.customDestroyed); } /** * Check that InitializingBean method is not called twice. */ public void testInitializingBeanAndSameInitMethod() throws Exception { InitAndIB.constructed = false; XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("initializers.xml", getClass())); assertFalse(InitAndIB.constructed); xbf.preInstantiateSingletons(); assertFalse(InitAndIB.constructed); InitAndIB iib = (InitAndIB) xbf.getBean("ib-same-init"); assertTrue(InitAndIB.constructed); assertTrue(iib.afterPropertiesSetInvoked && !iib.initMethodInvoked); assertTrue(!iib.destroyed && !iib.customDestroyed); xbf.destroySingletons(); assertTrue(iib.destroyed && !iib.customDestroyed); xbf.destroySingletons(); assertTrue(iib.destroyed && !iib.customDestroyed); } public void testDefaultLazyInit() throws Exception { InitAndIB.constructed = false; XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("default-lazy-init.xml", getClass())); assertFalse(InitAndIB.constructed); xbf.preInstantiateSingletons(); assertTrue(InitAndIB.constructed); try { xbf.getBean("lazy-and-bad"); } catch (BeanCreationException ex) { assertTrue(ex.getCause() instanceof ServletException); } } public void testNoSuchXmlFile() throws Exception { try { new XmlBeanFactory(new ClassPathResource("missing.xml", getClass())); fail("Must not create factory from missing XML"); } catch (BeanDefinitionStoreException expected) { } } public void testInvalidXmlFile() throws Exception { try { new XmlBeanFactory(new ClassPathResource("invalid.xml", getClass())); fail("Must not create factory from invalid XML"); } catch (BeanDefinitionStoreException expected) { } } public void testUnsatisfiedObjectDependencyCheck() throws Exception { try { XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("unsatisfiedObjectDependencyCheck.xml", getClass())); xbf.getBean("a", DependenciesBean.class); fail("Must have thrown an UnsatisfiedDependencyException"); } catch (UnsatisfiedDependencyException ex) { } } public void testUnsatisfiedSimpleDependencyCheck() throws Exception { try { XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("unsatisfiedSimpleDependencyCheck.xml", getClass())); xbf.getBean("a", DependenciesBean.class); fail("Must have thrown an UnsatisfiedDependencyException"); } catch (UnsatisfiedDependencyException expected) { } } public void testSatisfiedObjectDependencyCheck() throws Exception { XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("satisfiedObjectDependencyCheck.xml", getClass())); DependenciesBean a = (DependenciesBean) xbf.getBean("a"); assertNotNull(a.getSpouse()); assertEquals(xbf, a.getBeanFactory()); } public void testSatisfiedSimpleDependencyCheck() throws Exception { XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("satisfiedSimpleDependencyCheck.xml", getClass())); DependenciesBean a = (DependenciesBean) xbf.getBean("a"); assertEquals(a.getAge(), 33); } public void testUnsatisfiedAllDependencyCheck() throws Exception { try { XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("unsatisfiedAllDependencyCheckMissingObjects.xml", getClass())); xbf.getBean("a", DependenciesBean.class); fail("Must have thrown an UnsatisfiedDependencyException"); } catch (UnsatisfiedDependencyException expected) { } } public void testSatisfiedAllDependencyCheck() throws Exception { XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("satisfiedAllDependencyCheck.xml", getClass())); DependenciesBean a = (DependenciesBean) xbf.getBean("a"); assertEquals(a.getAge(), 33); assertNotNull(a.getName()); assertNotNull(a.getSpouse()); } public void testAutowire() throws Exception { XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("autowire.xml", getClass())); TestBean spouse = new TestBean("kerry", 0); xbf.registerSingleton("spouse", spouse); doTestAutowire(xbf); } public void testAutowireWithParent() throws Exception { XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("autowire.xml", getClass())); DefaultListableBeanFactory lbf = new DefaultListableBeanFactory(); MutablePropertyValues pvs = new MutablePropertyValues(); pvs.addPropertyValue("name", "kerry"); lbf.registerBeanDefinition("spouse", new RootBeanDefinition(TestBean.class, pvs)); xbf.setParentBeanFactory(lbf); doTestAutowire(xbf); } private void doTestAutowire(XmlBeanFactory xbf) throws Exception { DependenciesBean rod1 = (DependenciesBean) xbf.getBean("rod1"); TestBean kerry = (TestBean) xbf.getBean("spouse"); // should have been autowired assertEquals(kerry, rod1.getSpouse()); DependenciesBean rod1a = (DependenciesBean) xbf.getBean("rod1a"); // should have been autowired assertEquals(kerry, rod1a.getSpouse()); DependenciesBean rod2 = (DependenciesBean) xbf.getBean("rod2"); // should have been autowired assertEquals(kerry, rod2.getSpouse()); DependenciesBean rod2a = (DependenciesBean) xbf.getBean("rod2a"); // should have been set explicitly assertEquals(kerry, rod2a.getSpouse()); ConstructorDependenciesBean rod3 = (ConstructorDependenciesBean) xbf.getBean("rod3"); IndexedTestBean other = (IndexedTestBean) xbf.getBean("other"); // should have been autowired assertEquals(kerry, rod3.getSpouse1()); assertEquals(kerry, rod3.getSpouse2()); assertEquals(other, rod3.getOther()); ConstructorDependenciesBean rod3a = (ConstructorDependenciesBean) xbf.getBean("rod3a"); // should have been autowired assertEquals(kerry, rod3a.getSpouse1()); assertEquals(kerry, rod3a.getSpouse2()); assertEquals(other, rod3a.getOther()); try { xbf.getBean("rod4", ConstructorDependenciesBean.class); fail("Must have thrown a FatalBeanException"); } catch (FatalBeanException expected) { } DependenciesBean rod5 = (DependenciesBean) xbf.getBean("rod5"); // Should not have been autowired assertNull(rod5.getSpouse()); BeanFactory appCtx = (BeanFactory) xbf.getBean("childAppCtx"); assertTrue(appCtx.containsBean("rod1")); assertTrue(appCtx.containsBean("jenny")); } public void testAutowireWithDefault() throws Exception { XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("default-autowire.xml", getClass())); DependenciesBean rod1 = (DependenciesBean) xbf.getBean("rod1"); // should have been autowired assertNotNull(rod1.getSpouse()); assertTrue(rod1.getSpouse().getName().equals("Kerry")); DependenciesBean rod2 = (DependenciesBean) xbf.getBean("rod2"); // should have been autowired assertNotNull(rod2.getSpouse()); assertTrue(rod2.getSpouse().getName().equals("Kerry")); try { xbf.getBean("rod3", DependenciesBean.class); fail("Must have thrown UnsatisfiedDependencyException"); } catch (UnsatisfiedDependencyException expected) { } } public void testAutowireByConstructor() throws Exception { XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("constructor-arg.xml", getClass())); ConstructorDependenciesBean rod1 = (ConstructorDependenciesBean) xbf.getBean("rod1"); TestBean kerry = (TestBean) xbf.getBean("kerry2"); // should have been autowired assertEquals(kerry, rod1.getSpouse1()); assertEquals(0, rod1.getAge()); assertEquals(null, rod1.getName()); ConstructorDependenciesBean rod2 = (ConstructorDependenciesBean) xbf.getBean("rod2"); TestBean kerry1 = (TestBean) xbf.getBean("kerry1"); TestBean kerry2 = (TestBean) xbf.getBean("kerry2"); // should have been autowired assertEquals(kerry2, rod2.getSpouse1()); assertEquals(kerry1, rod2.getSpouse2()); assertEquals(0, rod2.getAge()); assertEquals(null, rod2.getName()); ConstructorDependenciesBean rod = (ConstructorDependenciesBean) xbf.getBean("rod3"); IndexedTestBean other = (IndexedTestBean) xbf.getBean("other"); // should have been autowired assertEquals(kerry, rod.getSpouse1()); assertEquals(kerry, rod.getSpouse2()); assertEquals(other, rod.getOther()); assertEquals(0, rod.getAge()); assertEquals(null, rod.getName()); xbf.getBean("rod4", ConstructorDependenciesBean.class); // should have been autowired assertEquals(kerry, rod.getSpouse1()); assertEquals(kerry, rod.getSpouse2()); assertEquals(other, rod.getOther()); assertEquals(0, rod.getAge()); assertEquals(null, rod.getName()); } public void testAutowireByConstructorWithSimpleValues() throws Exception { XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("constructor-arg.xml", getClass())); ConstructorDependenciesBean rod5 = (ConstructorDependenciesBean) xbf.getBean("rod5"); TestBean kerry1 = (TestBean) xbf.getBean("kerry1"); TestBean kerry2 = (TestBean) xbf.getBean("kerry2"); IndexedTestBean other = (IndexedTestBean) xbf.getBean("other"); // should have been autowired assertEquals(kerry2, rod5.getSpouse1()); assertEquals(kerry1, rod5.getSpouse2()); assertEquals(other, rod5.getOther()); assertEquals(99, rod5.getAge()); assertEquals("myname", rod5.getName()); DerivedConstructorDependenciesBean rod6 = (DerivedConstructorDependenciesBean) xbf.getBean("rod6"); // should have been autowired assertTrue(rod6.initialized); assertTrue(!rod6.destroyed); assertEquals(kerry2, rod6.getSpouse1()); assertEquals(kerry1, rod6.getSpouse2()); assertEquals(other, rod6.getOther()); assertEquals(0, rod6.getAge()); assertEquals(null, rod6.getName()); xbf.destroySingletons(); assertTrue(rod6.destroyed); } public void testRelatedCausesFromConstructorResolution() { XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("constructor-arg.xml", getClass())); try { xbf.getBean("rod2Accessor"); } catch (BeanCreationException ex) { assertTrue(ex.toString().indexOf("touchy") != -1); ex.printStackTrace(); assertNull(ex.getRelatedCauses()); } } public void testConstructorArgResolution() { XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("constructor-arg.xml", getClass())); TestBean kerry1 = (TestBean) xbf.getBean("kerry1"); TestBean kerry2 = (TestBean) xbf.getBean("kerry2"); ConstructorDependenciesBean rod9 = (ConstructorDependenciesBean) xbf.getBean("rod9"); assertEquals(99, rod9.getAge()); ConstructorDependenciesBean rod9a = (ConstructorDependenciesBean) xbf.getBean("rod9", new Object[] {new Integer(98)}); assertEquals(98, rod9a.getAge()); ConstructorDependenciesBean rod9b = (ConstructorDependenciesBean) xbf.getBean("rod9", new Object[] {"myName"}); assertEquals("myName", rod9b.getName()); ConstructorDependenciesBean rod9c = (ConstructorDependenciesBean) xbf.getBean("rod9", new Object[] {new Integer(97)}); assertEquals(97, rod9c.getAge()); ConstructorDependenciesBean rod10 = (ConstructorDependenciesBean) xbf.getBean("rod10"); assertEquals(null, rod10.getName()); ConstructorDependenciesBean rod11 = (ConstructorDependenciesBean) xbf.getBean("rod11"); assertEquals(kerry2, rod11.getSpouse1()); ConstructorDependenciesBean rod12 = (ConstructorDependenciesBean) xbf.getBean("rod12"); assertEquals(kerry1, rod12.getSpouse1()); assertNull(rod12.getSpouse2()); ConstructorDependenciesBean rod13 = (ConstructorDependenciesBean) xbf.getBean("rod13"); assertEquals(kerry1, rod13.getSpouse1()); assertEquals(kerry2, rod13.getSpouse2()); ConstructorDependenciesBean rod14 = (ConstructorDependenciesBean) xbf.getBean("rod14"); assertEquals(kerry1, rod14.getSpouse1()); assertEquals(kerry2, rod14.getSpouse2()); ConstructorDependenciesBean rod15 = (ConstructorDependenciesBean) xbf.getBean("rod15"); assertEquals(kerry2, rod15.getSpouse1()); assertEquals(kerry1, rod15.getSpouse2()); ConstructorDependenciesBean rod16 = (ConstructorDependenciesBean) xbf.getBean("rod16"); assertEquals(kerry2, rod16.getSpouse1()); assertEquals(kerry1, rod16.getSpouse2()); assertEquals(29, rod16.getAge()); } public void testConstructorArgWithSingleMatch() { XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("constructor-arg.xml", getClass())); File file = (File) xbf.getBean("file"); assertEquals(File.separator + "test", file.getPath()); } public void testThrowsExceptionOnTooManyArguments() throws Exception { XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("constructor-arg.xml", getClass())); try { xbf.getBean("rod7", ConstructorDependenciesBean.class); fail("Should have thrown BeanCreationException"); } catch (BeanCreationException expected) { } } public void testThrowsExceptionOnAmbiguousResolution() throws Exception { XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("constructor-arg.xml", getClass())); try { xbf.getBean("rod8", ConstructorDependenciesBean.class); fail("Must have thrown UnsatisfiedDependencyException"); } catch (UnsatisfiedDependencyException expected) { } } public void testDependsOn() { doTestDependencies("dependencies-dependsOn.xml", 1); } public void testDependsOnInInnerBean() { doTestDependencies("dependencies-dependsOn-inner.xml", 4); } public void testDependenciesThroughConstructorArguments() { doTestDependencies("dependencies-carg.xml", 1); } public void testDependenciesThroughConstructorArgumentAutowiring() { doTestDependencies("dependencies-carg-autowire.xml", 1); } public void testDependenciesThroughConstructorArgumentsInInnerBean() { doTestDependencies("dependencies-carg-inner.xml", 1); } public void testDependenciesThroughProperties() { doTestDependencies("dependencies-prop.xml", 1); } public void testDependenciesThroughPropertiesWithInTheMiddle() { doTestDependencies("dependencies-prop-inTheMiddle.xml", 1); } public void testDependenciesThroughPropertyAutowiringByName() { doTestDependencies("dependencies-prop-autowireByName.xml", 1); } public void testDependenciesThroughPropertyAutowiringByType() { doTestDependencies("dependencies-prop-autowireByType.xml", 1); } public void testDependenciesThroughPropertiesInInnerBean() { doTestDependencies("dependencies-prop-inner.xml", 1); } private void doTestDependencies(String filename, int nrOfHoldingBeans) { PreparingBean1.prepared = false; PreparingBean1.destroyed = false; PreparingBean2.prepared = false; PreparingBean2.destroyed = false; DependingBean.destroyCount = 0; HoldingBean.destroyCount = 0; XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource(filename, getClass())); xbf.preInstantiateSingletons(); xbf.destroySingletons(); assertTrue(PreparingBean1.prepared); assertTrue(PreparingBean1.destroyed); assertTrue(PreparingBean2.prepared); assertTrue(PreparingBean2.destroyed); assertEquals(nrOfHoldingBeans, DependingBean.destroyCount); if (!xbf.getBeansOfType(HoldingBean.class, false, false).isEmpty()) { assertEquals(nrOfHoldingBeans, HoldingBean.destroyCount); } } /** * When using a BeanFactory. singletons are of course not pre-instantiated. * So rubbish class names in bean defs must now not be 'resolved' when the * bean def is being parsed, 'cos everything on a bean def is now lazy, but * must rather only be picked up when the bean is instantiated. */ public void testClassNotFoundWithDefaultBeanClassLoader() { BeanFactory factory = new XmlBeanFactory(new ClassPathResource("classNotFound.xml", getClass())); // cool, no errors, so the rubbish class name in the bean def was not resolved try { // let's resolve the bean definition; must blow up factory.getBean("classNotFound"); fail("Must have thrown a CannotLoadBeanClassException"); } catch (CannotLoadBeanClassException ex) { assertTrue(ex.getResourceDescription().indexOf("classNotFound.xml") != -1); assertTrue(ex.getCause() instanceof ClassNotFoundException); } } public void testClassNotFoundWithNoBeanClassLoader() { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(bf); reader.setBeanClassLoader(null); reader.loadBeanDefinitions(new ClassPathResource("classNotFound.xml", getClass())); assertEquals("WhatALotOfRubbish", bf.getBeanDefinition("classNotFound").getBeanClassName()); } public void testResourceAndInputStream() throws IOException { XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("resource.xml", getClass())); // comes from "resourceImport.xml" ResourceTestBean resource1 = (ResourceTestBean) xbf.getBean("resource1"); // comes from "resource.xml" ResourceTestBean resource2 = (ResourceTestBean) xbf.getBean("resource2"); assertTrue(resource1.getResource() instanceof ClassPathResource); StringWriter writer = new StringWriter(); FileCopyUtils.copy(new InputStreamReader(resource1.getResource().getInputStream()), writer); assertEquals("test", writer.toString()); writer = new StringWriter(); FileCopyUtils.copy(new InputStreamReader(resource1.getInputStream()), writer); assertEquals("test", writer.toString()); writer = new StringWriter(); FileCopyUtils.copy(new InputStreamReader(resource2.getResource().getInputStream()), writer); assertEquals("test", writer.toString()); writer = new StringWriter(); FileCopyUtils.copy(new InputStreamReader(resource2.getInputStream()), writer); assertEquals("test", writer.toString()); } public void testClassPathResourceWithImport() { XmlBeanFactory xbf = new XmlBeanFactory( new ClassPathResource("org/springframework/beans/factory/xml/resource.xml")); // comes from "resourceImport.xml" xbf.getBean("resource1", ResourceTestBean.class); // comes from "resource.xml" xbf.getBean("resource2", ResourceTestBean.class); } public void testUrlResourceWithImport() { URL url = getClass().getResource("resource.xml"); XmlBeanFactory xbf = new XmlBeanFactory(new UrlResource(url)); // comes from "resourceImport.xml" xbf.getBean("resource1", ResourceTestBean.class); // comes from "resource.xml" xbf.getBean("resource2", ResourceTestBean.class); } public void testFileSystemResourceWithImport() { String file = getClass().getResource("resource.xml").getFile(); XmlBeanFactory xbf = new XmlBeanFactory(new FileSystemResource(file)); // comes from "resourceImport.xml" xbf.getBean("resource1", ResourceTestBean.class); // comes from "resource.xml" xbf.getBean("resource2", ResourceTestBean.class); } public void testRecursiveImport() { try { XmlBeanFactory xbf = new XmlBeanFactory( new ClassPathResource("org/springframework/beans/factory/xml/recursiveImport.xml")); fail("Should have thrown BeanDefinitionStoreException"); } catch (BeanDefinitionStoreException ex) { // expected ex.printStackTrace(); } } public void testLookupOverrideMethodsWithSetterInjection() { DefaultListableBeanFactory xbf = new DefaultListableBeanFactory(); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf); reader.loadBeanDefinitions(new ClassPathResource("overrides.xml", getClass())); testLookupOverrideMethodsWithSetterInjection(xbf, "overrideOneMethod", true); // Should work identically on subclass definition, in which lookup // methods are inherited testLookupOverrideMethodsWithSetterInjection(xbf, "overrideInheritedMethod", true); // Check cost of repeated construction of beans with method overrides // Will pick up misuse of CGLIB int howMany = 100; StopWatch sw = new StopWatch(); sw.start("Look up " + howMany + " prototype bean instances with method overrides"); for (int i = 0; i < howMany; i++) { testLookupOverrideMethodsWithSetterInjection(xbf, "overrideOnPrototype", false); } sw.stop(); System.out.println(sw); if (!LogFactory.getLog(DefaultListableBeanFactory.class).isDebugEnabled()) { assertTrue(sw.getTotalTimeMillis() < 2000); } // Now test distinct bean with swapped value in factory, to ensure the two are independent OverrideOneMethod swappedOom = (OverrideOneMethod) xbf.getBean("overrideOneMethodSwappedReturnValues"); TestBean tb = swappedOom.getPrototypeDependency(); assertEquals("David", tb.getName()); tb = swappedOom.protectedOverrideSingleton(); assertEquals("Jenny", tb.getName()); } private void testLookupOverrideMethodsWithSetterInjection(BeanFactory xbf, String beanName, boolean singleton) { OverrideOneMethod oom = (OverrideOneMethod) xbf.getBean(beanName); if (singleton) { assertSame(oom, xbf.getBean(beanName)); } else { assertNotSame(oom, xbf.getBean(beanName)); } TestBean jenny1 = oom.getPrototypeDependency(); assertEquals("Jenny", jenny1.getName()); TestBean jenny2 = oom.getPrototypeDependency(); assertEquals("Jenny", jenny2.getName()); assertNotSame(jenny1, jenny2); // Check that the bean can invoke the overridden method on itself // This differs from Spring's AOP support, which has a distinct notion // of a "target" object, meaning that the target needs explicit knowledge // of AOP proxying to invoke an advised method on itself. TestBean jenny3 = oom.invokesOverridenMethodOnSelf(); assertEquals("Jenny", jenny3.getName()); assertNotSame(jenny1, jenny3); // Now try protected method, and singleton TestBean dave1 = oom.protectedOverrideSingleton(); assertEquals("David", dave1.getName()); TestBean dave2 = oom.protectedOverrideSingleton(); assertEquals("David", dave2.getName()); assertSame(dave1, dave2); } public void testReplaceMethodOverrideWithSetterInjection() { DefaultListableBeanFactory xbf = new DefaultListableBeanFactory(); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf); reader.loadBeanDefinitions(new ClassPathResource("delegationOverrides.xml", getClass())); OverrideOneMethod oom = (OverrideOneMethod) xbf.getBean("overrideOneMethod"); // Same contract as for overrides.xml TestBean jenny1 = oom.getPrototypeDependency(); assertEquals("Jenny", jenny1.getName()); TestBean jenny2 = oom.getPrototypeDependency(); assertEquals("Jenny", jenny2.getName()); assertNotSame(jenny1, jenny2); TestBean notJenny = oom.getPrototypeDependency("someParam"); assertTrue(!"Jenny".equals(notJenny.getName())); // Now try protected method, and singleton TestBean dave1 = oom.protectedOverrideSingleton(); assertEquals("David", dave1.getName()); TestBean dave2 = oom.protectedOverrideSingleton(); assertEquals("David", dave2.getName()); assertSame(dave1, dave2); // Check unadvised behaviour String str = "woierowijeiowiej"; assertEquals(str, oom.echo(str)); // Now test replace String s = "this is not a palindrome"; String reverse = new StringBuffer(s).reverse().toString(); assertEquals("Should have overridden to reverse, not echo", reverse, oom.replaceMe(s)); assertEquals("Should have overridden no-arg overloaded replaceMe method to return fixed value", FixedMethodReplacer.VALUE, oom.replaceMe()); OverrideOneMethodSubclass ooms = (OverrideOneMethodSubclass) xbf.getBean("replaceVoidMethod"); DoSomethingReplacer dos = (DoSomethingReplacer) xbf.getBean("doSomethingReplacer"); assertEquals(null, dos.lastArg); String s1 = ""; String s2 = "foo bar black sheep"; ooms.doSomething(s1); assertEquals(s1, dos.lastArg); ooms.doSomething(s2); assertEquals(s2, dos.lastArg); } public void testLookupOverrideOneMethodWithConstructorInjection() { DefaultListableBeanFactory xbf = new DefaultListableBeanFactory(); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf); reader.loadBeanDefinitions(new ClassPathResource("constructorOverrides.xml", getClass())); ConstructorInjectedOverrides cio = (ConstructorInjectedOverrides) xbf.getBean("constructorOverrides"); // Check that the setter was invoked... // We should be able to combine Constructor and // Setter Injection assertEquals("Setter string was set", "from property element", cio.getSetterString()); // Jenny is a singleton TestBean jenny = (TestBean) xbf.getBean("jenny"); assertSame(jenny, cio.getTestBean()); assertSame(jenny, cio.getTestBean()); FactoryMethods fm1 = cio.createFactoryMethods(); FactoryMethods fm2 = cio.createFactoryMethods(); assertNotSame("FactoryMethods reference is to a prototype", fm1, fm2); assertSame("The two prototypes hold the same singleton reference", fm1.getTestBean(), fm2.getTestBean()); } public void testRejectsOverrideOfBogusMethodName() { DefaultListableBeanFactory xbf = new DefaultListableBeanFactory(); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf); try { reader.loadBeanDefinitions(new ClassPathResource("invalidOverridesNoSuchMethod.xml", getClass())); xbf.getBean("constructorOverrides"); fail("Shouldn't allow override of bogus method"); } catch (BeanDefinitionStoreException ex) { // Check that the bogus method name was included in the error message assertTrue("Bogus method name correctly reported", ex.getMessage().indexOf("bogusMethod") != -1); } } /** * Assert the presence of this bug until we resolve it. */ public void testSerializabilityOfMethodReplacer() throws Exception { try { BUGtestSerializableMethodReplacerAndSuperclass(); fail(); } catch (AssertionFailedError ex) { System.err.println("****** SPR-356: Objects with MethodReplace overrides are not serializable"); } } public void BUGtestSerializableMethodReplacerAndSuperclass() throws IOException, ClassNotFoundException { DefaultListableBeanFactory xbf = new DefaultListableBeanFactory(); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf); reader.loadBeanDefinitions(new ClassPathResource("delegationOverrides.xml", getClass())); SerializableMethodReplacerCandidate s = (SerializableMethodReplacerCandidate) xbf.getBean("serializableReplacer"); String forwards = "this is forwards"; String backwards = new StringBuffer(forwards).reverse().toString(); assertEquals(backwards, s.replaceMe(forwards)); assertTrue(SerializationTestUtils.isSerializable(s)); s = (SerializableMethodReplacerCandidate) SerializationTestUtils.serializeAndDeserialize(s); assertEquals("Method replace still works after serialization and deserialization", backwards, s.replaceMe(forwards)); } public void testInnerBeanInheritsScopeFromConcreteChildDefinition() { DefaultListableBeanFactory xbf = new DefaultListableBeanFactory(); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf); reader.loadBeanDefinitions(new ClassPathResource("overrides.xml", getClass())); TestBean jenny = (TestBean) xbf.getBean("jennyChild"); assertEquals(1, jenny.getFriends().size()); assertTrue(jenny.getFriends().iterator().next() instanceof TestBean); } public void testConstructorArgWithSingleSimpleTypeMatch() { XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("constructor-arg.xml", getClass())); SingleSimpleTypeConstructorBean bean = (SingleSimpleTypeConstructorBean) xbf.getBean("beanWithBoolean"); assertTrue(bean.isSingleBoolean()); SingleSimpleTypeConstructorBean bean2 = (SingleSimpleTypeConstructorBean) xbf.getBean("beanWithBoolean2"); assertTrue(bean2.isSingleBoolean()); } public void testConstructorArgWithDoubleSimpleTypeMatch() { XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("constructor-arg.xml", getClass())); SingleSimpleTypeConstructorBean bean = (SingleSimpleTypeConstructorBean) xbf.getBean("beanWithBooleanAndString"); assertTrue(bean.isSecondBoolean()); assertEquals("A String", bean.getTestString()); SingleSimpleTypeConstructorBean bean2 = (SingleSimpleTypeConstructorBean) xbf.getBean("beanWithBooleanAndString2"); assertTrue(bean2.isSecondBoolean()); assertEquals("A String", bean2.getTestString()); } public void testDoubleBooleanAutowire() { XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("constructor-arg.xml", getClass())); DoubleBooleanConstructorBean bean = (DoubleBooleanConstructorBean) xbf.getBean("beanWithDoubleBoolean"); assertEquals(Boolean.TRUE, bean.boolean1); assertEquals(Boolean.FALSE, bean.boolean2); } public void testDoubleBooleanAutowireWithIndex() { XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("constructor-arg.xml", getClass())); DoubleBooleanConstructorBean bean = (DoubleBooleanConstructorBean) xbf.getBean("beanWithDoubleBooleanAndIndex"); assertEquals(Boolean.FALSE, bean.boolean1); assertEquals(Boolean.TRUE, bean.boolean2); } public void testWithDuplicateName() throws Exception { try { new XmlBeanFactory(new ClassPathResource("testWithDuplicateNames.xml", getClass())); fail("Duplicate name not detected"); } catch (BeansException ex) { assertTrue(ex.getMessage().indexOf("Bean name 'foo'") > -1); } } public void testWithDuplicateNameInAlias() throws Exception { try { new XmlBeanFactory(new ClassPathResource("testWithDuplicateNameInAlias.xml", getClass())); fail("Duplicate name not detected"); } catch (BeansException e) { assertTrue(e.getMessage().indexOf("Bean name 'foo'") > -1); } } public static class DoSomethingReplacer implements MethodReplacer { public Object lastArg; public Object reimplement(Object obj, Method method, Object[] args) throws Throwable { assertEquals(1, args.length); assertEquals("doSomething", method.getName()); lastArg = args[0]; return null; } } public static class BadInitializer { /** Init method */ public void init2() throws ServletException { throw new ServletException(); } } public static class DoubleInitializer { private int num; public int getNum() { return num; } public void setNum(int i) { num = i; } /** Init method */ public void init() { this.num *= 2; } } public static class InitAndIB implements InitializingBean, DisposableBean { public static boolean constructed; public boolean afterPropertiesSetInvoked, initMethodInvoked, destroyed, customDestroyed; public InitAndIB() { constructed = true; } public void afterPropertiesSet() { if (this.initMethodInvoked) { fail(); } if (this.afterPropertiesSetInvoked) { throw new IllegalStateException("Already initialized"); } this.afterPropertiesSetInvoked = true; } /** Init method */ public void customInit() throws ServletException { if (!this.afterPropertiesSetInvoked) { fail(); } if (this.initMethodInvoked) { throw new IllegalStateException("Already customInitialized"); } this.initMethodInvoked = true; } public void destroy() { if (this.customDestroyed) { fail(); } if (this.destroyed) { throw new IllegalStateException("Already destroyed"); } this.destroyed = true; } public void customDestroy() { if (!this.destroyed) { fail(); } if (this.customDestroyed) { throw new IllegalStateException("Already customDestroyed"); } this.customDestroyed = true; } } public static class PreparingBean1 implements DisposableBean { public static boolean prepared = false; public static boolean destroyed = false; public PreparingBean1() { prepared = true; } public void destroy() { destroyed = true; } } public static class PreparingBean2 implements DisposableBean { public static boolean prepared = false; public static boolean destroyed = false; public PreparingBean2() { prepared = true; } public void destroy() { destroyed = true; } } public static class DependingBean implements InitializingBean, DisposableBean { public static int destroyCount = 0; public boolean destroyed = false; public DependingBean() { } public DependingBean(PreparingBean1 bean1, PreparingBean2 bean2) { } public void setBean1(PreparingBean1 bean1) { } public void setBean2(PreparingBean2 bean2) { } public void setInTheMiddleBean(InTheMiddleBean bean) { } public void afterPropertiesSet() { if (!(PreparingBean1.prepared && PreparingBean2.prepared)) { throw new IllegalStateException("Need prepared PreparingBeans!"); } } public void destroy() { if (PreparingBean1.destroyed || PreparingBean2.destroyed) { throw new IllegalStateException("Should not be destroyed after PreparingBeans"); } destroyed = true; destroyCount++; } } public static class InTheMiddleBean { public void setBean1(PreparingBean1 bean1) { } public void setBean2(PreparingBean2 bean2) { } } public static class HoldingBean implements DisposableBean { public static int destroyCount = 0; private DependingBean dependingBean; public boolean destroyed = false; public void setDependingBean(DependingBean dependingBean) { this.dependingBean = dependingBean; } public void destroy() { if (this.dependingBean.destroyed) { throw new IllegalStateException("Should not be destroyed after DependingBean"); } this.destroyed = true; destroyCount++; } } public static class DoubleBooleanConstructorBean { private Boolean boolean1; private Boolean boolean2; public DoubleBooleanConstructorBean(Boolean b1, Boolean b2) { this.boolean1 = b1; this.boolean2 = b2; } } public static class WrappingPostProcessor implements BeanPostProcessor { public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; } public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { ProxyFactory pf = new ProxyFactory(bean); return pf.getProxy(); } } }