Browse Source
git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@202 50f2f4bb-b051-0410-bef5-90022cba6387pull/1/head
12 changed files with 1226 additions and 56 deletions
@ -0,0 +1,329 @@
@@ -0,0 +1,329 @@
|
||||
/* |
||||
* 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; |
||||
|
||||
import java.beans.PropertyEditorSupport; |
||||
import java.util.StringTokenizer; |
||||
|
||||
import junit.framework.TestCase; |
||||
import junit.framework.Assert; |
||||
|
||||
import org.springframework.beans.BeansException; |
||||
import org.springframework.beans.PropertyBatchUpdateException; |
||||
import org.springframework.beans.TestBean; |
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory; |
||||
|
||||
/** |
||||
* Subclasses must implement setUp() to initialize bean factory |
||||
* and any other variables they need. |
||||
* |
||||
* @author Rod Johnson |
||||
* @author Juergen Hoeller |
||||
*/ |
||||
public abstract class AbstractBeanFactoryTests extends TestCase { |
||||
|
||||
protected abstract BeanFactory getBeanFactory(); |
||||
|
||||
/** |
||||
* Roderick beans inherits from rod, overriding name only. |
||||
*/ |
||||
public void testInheritance() { |
||||
assertTrue(getBeanFactory().containsBean("rod")); |
||||
assertTrue(getBeanFactory().containsBean("roderick")); |
||||
TestBean rod = (TestBean) getBeanFactory().getBean("rod"); |
||||
TestBean roderick = (TestBean) getBeanFactory().getBean("roderick"); |
||||
assertTrue("not == ", rod != roderick); |
||||
assertTrue("rod.name is Rod", rod.getName().equals("Rod")); |
||||
assertTrue("rod.age is 31", rod.getAge() == 31); |
||||
assertTrue("roderick.name is Roderick", roderick.getName().equals("Roderick")); |
||||
assertTrue("roderick.age was inherited", roderick.getAge() == rod.getAge()); |
||||
} |
||||
|
||||
public void testGetBeanWithNullArg() { |
||||
try { |
||||
getBeanFactory().getBean(null); |
||||
fail("Can't get null bean"); |
||||
} |
||||
catch (IllegalArgumentException ex) { |
||||
// OK
|
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Test that InitializingBean objects receive the afterPropertiesSet() callback |
||||
*/ |
||||
public void testInitializingBeanCallback() { |
||||
MustBeInitialized mbi = (MustBeInitialized) getBeanFactory().getBean("mustBeInitialized"); |
||||
// The dummy business method will throw an exception if the
|
||||
// afterPropertiesSet() callback wasn't invoked
|
||||
mbi.businessMethod(); |
||||
} |
||||
|
||||
/** |
||||
* Test that InitializingBean/BeanFactoryAware/DisposableBean objects receive the |
||||
* afterPropertiesSet() callback before BeanFactoryAware callbacks |
||||
*/ |
||||
public void testLifecycleCallbacks() { |
||||
LifecycleBean lb = (LifecycleBean) getBeanFactory().getBean("lifecycle"); |
||||
Assert.assertEquals("lifecycle", lb.getBeanName()); |
||||
// The dummy business method will throw an exception if the
|
||||
// necessary callbacks weren't invoked in the right order.
|
||||
lb.businessMethod(); |
||||
assertTrue("Not destroyed", !lb.isDestroyed()); |
||||
} |
||||
|
||||
public void testFindsValidInstance() { |
||||
try { |
||||
Object o = getBeanFactory().getBean("rod"); |
||||
assertTrue("Rod bean is a TestBean", o instanceof TestBean); |
||||
TestBean rod = (TestBean) o; |
||||
assertTrue("rod.name is Rod", rod.getName().equals("Rod")); |
||||
assertTrue("rod.age is 31", rod.getAge() == 31); |
||||
} |
||||
catch (Exception ex) { |
||||
ex.printStackTrace(); |
||||
fail("Shouldn't throw exception on getting valid instance"); |
||||
} |
||||
} |
||||
|
||||
public void testGetInstanceByMatchingClass() { |
||||
try { |
||||
Object o = getBeanFactory().getBean("rod", TestBean.class); |
||||
assertTrue("Rod bean is a TestBean", o instanceof TestBean); |
||||
} |
||||
catch (Exception ex) { |
||||
ex.printStackTrace(); |
||||
fail("Shouldn't throw exception on getting valid instance with matching class"); |
||||
} |
||||
} |
||||
|
||||
public void testGetInstanceByNonmatchingClass() { |
||||
try { |
||||
Object o = getBeanFactory().getBean("rod", BeanFactory.class); |
||||
fail("Rod bean is not of type BeanFactory; getBeanInstance(rod, BeanFactory.class) should throw BeanNotOfRequiredTypeException"); |
||||
} |
||||
catch (BeanNotOfRequiredTypeException ex) { |
||||
// So far, so good
|
||||
assertTrue("Exception has correct bean name", ex.getBeanName().equals("rod")); |
||||
assertTrue("Exception requiredType must be BeanFactory.class", ex.getRequiredType().equals(BeanFactory.class)); |
||||
assertTrue("Exception actualType as TestBean.class", TestBean.class.isAssignableFrom(ex.getActualType())); |
||||
assertTrue("Actual type is correct", ex.getActualType() == getBeanFactory().getBean("rod").getClass()); |
||||
} |
||||
catch (Exception ex) { |
||||
ex.printStackTrace(); |
||||
fail("Shouldn't throw exception on getting valid instance"); |
||||
} |
||||
} |
||||
|
||||
public void testGetSharedInstanceByMatchingClass() { |
||||
try { |
||||
Object o = getBeanFactory().getBean("rod", TestBean.class); |
||||
assertTrue("Rod bean is a TestBean", o instanceof TestBean); |
||||
} |
||||
catch (Exception ex) { |
||||
ex.printStackTrace(); |
||||
fail("Shouldn't throw exception on getting valid instance with matching class"); |
||||
} |
||||
} |
||||
|
||||
public void testGetSharedInstanceByMatchingClassNoCatch() { |
||||
Object o = getBeanFactory().getBean("rod", TestBean.class); |
||||
assertTrue("Rod bean is a TestBean", o instanceof TestBean); |
||||
} |
||||
|
||||
public void testGetSharedInstanceByNonmatchingClass() { |
||||
try { |
||||
Object o = getBeanFactory().getBean("rod", BeanFactory.class); |
||||
fail("Rod bean is not of type BeanFactory; getBeanInstance(rod, BeanFactory.class) should throw BeanNotOfRequiredTypeException"); |
||||
} |
||||
catch (BeanNotOfRequiredTypeException ex) { |
||||
// So far, so good
|
||||
assertTrue("Exception has correct bean name", ex.getBeanName().equals("rod")); |
||||
assertTrue("Exception requiredType must be BeanFactory.class", ex.getRequiredType().equals(BeanFactory.class)); |
||||
assertTrue("Exception actualType as TestBean.class", TestBean.class.isAssignableFrom(ex.getActualType())); |
||||
} |
||||
catch (Exception ex) { |
||||
ex.printStackTrace(); |
||||
fail("Shouldn't throw exception on getting valid instance"); |
||||
} |
||||
} |
||||
|
||||
public void testSharedInstancesAreEqual() { |
||||
try { |
||||
Object o = getBeanFactory().getBean("rod"); |
||||
assertTrue("Rod bean1 is a TestBean", o instanceof TestBean); |
||||
Object o1 = getBeanFactory().getBean("rod"); |
||||
assertTrue("Rod bean2 is a TestBean", o1 instanceof TestBean); |
||||
assertTrue("Object equals applies", o == o1); |
||||
} |
||||
catch (Exception ex) { |
||||
ex.printStackTrace(); |
||||
fail("Shouldn't throw exception on getting valid instance"); |
||||
} |
||||
} |
||||
|
||||
public void testPrototypeInstancesAreIndependent() { |
||||
TestBean tb1 = (TestBean) getBeanFactory().getBean("kathy"); |
||||
TestBean tb2 = (TestBean) getBeanFactory().getBean("kathy"); |
||||
assertTrue("ref equal DOES NOT apply", tb1 != tb2); |
||||
assertTrue("object equal true", tb1.equals(tb2)); |
||||
tb1.setAge(1); |
||||
tb2.setAge(2); |
||||
assertTrue("1 age independent = 1", tb1.getAge() == 1); |
||||
assertTrue("2 age independent = 2", tb2.getAge() == 2); |
||||
assertTrue("object equal now false", !tb1.equals(tb2)); |
||||
} |
||||
|
||||
public void testNotThere() { |
||||
assertFalse(getBeanFactory().containsBean("Mr Squiggle")); |
||||
try { |
||||
Object o = getBeanFactory().getBean("Mr Squiggle"); |
||||
fail("Can't find missing bean"); |
||||
} |
||||
catch (BeansException ex) { |
||||
//ex.printStackTrace();
|
||||
//fail("Shouldn't throw exception on getting valid instance");
|
||||
} |
||||
} |
||||
|
||||
public void testValidEmpty() { |
||||
try { |
||||
Object o = getBeanFactory().getBean("validEmpty"); |
||||
assertTrue("validEmpty bean is a TestBean", o instanceof TestBean); |
||||
TestBean ve = (TestBean) o; |
||||
assertTrue("Valid empty has defaults", ve.getName() == null && ve.getAge() == 0 && ve.getSpouse() == null); |
||||
} |
||||
catch (BeansException ex) { |
||||
ex.printStackTrace(); |
||||
fail("Shouldn't throw exception on valid empty"); |
||||
} |
||||
} |
||||
|
||||
public void xtestTypeMismatch() { |
||||
try { |
||||
Object o = getBeanFactory().getBean("typeMismatch"); |
||||
fail("Shouldn't succeed with type mismatch"); |
||||
} |
||||
catch (BeanCreationException wex) { |
||||
assertEquals("typeMismatch", wex.getBeanName()); |
||||
assertTrue(wex.getCause() instanceof PropertyBatchUpdateException); |
||||
PropertyBatchUpdateException ex = (PropertyBatchUpdateException) wex.getCause(); |
||||
// Further tests
|
||||
assertTrue("Has one error ", ex.getExceptionCount() == 1); |
||||
assertTrue("Error is for field age", ex.getPropertyAccessException("age") != null); |
||||
assertTrue("We have rejected age in exception", ex.getPropertyAccessException("age").getPropertyChangeEvent().getNewValue().equals("34x")); |
||||
} |
||||
} |
||||
|
||||
public void testGrandparentDefinitionFoundInBeanFactory() throws Exception { |
||||
TestBean dad = (TestBean) getBeanFactory().getBean("father"); |
||||
assertTrue("Dad has correct name", dad.getName().equals("Albert")); |
||||
} |
||||
|
||||
public void testFactorySingleton() throws Exception { |
||||
assertTrue(getBeanFactory().isSingleton("&singletonFactory")); |
||||
assertTrue(getBeanFactory().isSingleton("singletonFactory")); |
||||
TestBean tb = (TestBean) getBeanFactory().getBean("singletonFactory"); |
||||
assertTrue("Singleton from factory has correct name, not " + tb.getName(), tb.getName().equals(DummyFactory.SINGLETON_NAME)); |
||||
DummyFactory factory = (DummyFactory) getBeanFactory().getBean("&singletonFactory"); |
||||
TestBean tb2 = (TestBean) getBeanFactory().getBean("singletonFactory"); |
||||
assertTrue("Singleton references ==", tb == tb2); |
||||
assertTrue("FactoryBean is BeanFactoryAware", factory.getBeanFactory() != null); |
||||
} |
||||
|
||||
public void testFactoryPrototype() throws Exception { |
||||
assertTrue(getBeanFactory().isSingleton("&prototypeFactory")); |
||||
assertFalse(getBeanFactory().isSingleton("prototypeFactory")); |
||||
TestBean tb = (TestBean) getBeanFactory().getBean("prototypeFactory"); |
||||
assertTrue(!tb.getName().equals(DummyFactory.SINGLETON_NAME)); |
||||
TestBean tb2 = (TestBean) getBeanFactory().getBean("prototypeFactory"); |
||||
assertTrue("Prototype references !=", tb != tb2); |
||||
} |
||||
|
||||
/** |
||||
* Check that we can get the factory bean itself. |
||||
* This is only possible if we're dealing with a factory |
||||
* @throws Exception |
||||
*/ |
||||
public void testGetFactoryItself() throws Exception { |
||||
DummyFactory factory = (DummyFactory) getBeanFactory().getBean("&singletonFactory"); |
||||
assertTrue(factory != null); |
||||
} |
||||
|
||||
/** |
||||
* Check that afterPropertiesSet gets called on factory |
||||
* @throws Exception |
||||
*/ |
||||
public void testFactoryIsInitialized() throws Exception { |
||||
TestBean tb = (TestBean) getBeanFactory().getBean("singletonFactory"); |
||||
DummyFactory factory = (DummyFactory) getBeanFactory().getBean("&singletonFactory"); |
||||
assertTrue("Factory was initialized because it implemented InitializingBean", factory.wasInitialized()); |
||||
} |
||||
|
||||
/** |
||||
* It should be illegal to dereference a normal bean |
||||
* as a factory |
||||
*/ |
||||
public void testRejectsFactoryGetOnNormalBean() { |
||||
try { |
||||
getBeanFactory().getBean("&rod"); |
||||
fail("Shouldn't permit factory get on normal bean"); |
||||
} |
||||
catch (BeanIsNotAFactoryException ex) { |
||||
// Ok
|
||||
} |
||||
} |
||||
|
||||
// TODO: refactor in AbstractBeanFactory (tests for AbstractBeanFactory)
|
||||
// and rename this class
|
||||
public void testAliasing() { |
||||
BeanFactory bf = getBeanFactory(); |
||||
if (!(bf instanceof ConfigurableBeanFactory)) { |
||||
return; |
||||
} |
||||
ConfigurableBeanFactory cbf = (ConfigurableBeanFactory) bf; |
||||
|
||||
String alias = "rods alias"; |
||||
try { |
||||
cbf.getBean(alias); |
||||
fail("Shouldn't permit factory get on normal bean"); |
||||
} |
||||
catch (NoSuchBeanDefinitionException ex) { |
||||
// Ok
|
||||
assertTrue(alias.equals(ex.getBeanName())); |
||||
} |
||||
|
||||
// Create alias
|
||||
cbf.registerAlias("rod", alias); |
||||
Object rod = getBeanFactory().getBean("rod"); |
||||
Object aliasRod = getBeanFactory().getBean(alias); |
||||
assertTrue(rod == aliasRod); |
||||
} |
||||
|
||||
|
||||
public static class TestBeanEditor extends PropertyEditorSupport { |
||||
|
||||
public void setAsText(String text) { |
||||
TestBean tb = new TestBean(); |
||||
StringTokenizer st = new StringTokenizer(text, "_"); |
||||
tb.setName(st.nextToken()); |
||||
tb.setAge(Integer.parseInt(st.nextToken())); |
||||
setValue(tb); |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,86 @@
@@ -0,0 +1,86 @@
|
||||
/* |
||||
* Copyright 2002-2007 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; |
||||
|
||||
import junit.framework.Assert; |
||||
|
||||
import org.springframework.beans.TestBean; |
||||
|
||||
/** |
||||
* @author Rod Johnson |
||||
* @author Juergen Hoeller |
||||
*/ |
||||
public abstract class AbstractListableBeanFactoryTests extends AbstractBeanFactoryTests { |
||||
|
||||
/** Subclasses must initialize this */ |
||||
protected ListableBeanFactory getListableBeanFactory() { |
||||
BeanFactory bf = getBeanFactory(); |
||||
if (!(bf instanceof ListableBeanFactory)) { |
||||
throw new IllegalStateException("ListableBeanFactory required"); |
||||
} |
||||
return (ListableBeanFactory) bf; |
||||
} |
||||
|
||||
/** |
||||
* Subclasses can override this. |
||||
*/ |
||||
public void testCount() { |
||||
assertCount(13); |
||||
} |
||||
|
||||
protected final void assertCount(int count) { |
||||
String[] defnames = getListableBeanFactory().getBeanDefinitionNames(); |
||||
Assert.assertTrue("We should have " + count + " beans, not " + defnames.length, defnames.length == count); |
||||
} |
||||
|
||||
public void assertTestBeanCount(int count) { |
||||
String[] defNames = getListableBeanFactory().getBeanNamesForType(TestBean.class, true, false); |
||||
Assert.assertTrue("We should have " + count + " beans for class org.springframework.beans.TestBean, not " + |
||||
defNames.length, defNames.length == count); |
||||
|
||||
int countIncludingFactoryBeans = count + 2; |
||||
String[] names = getListableBeanFactory().getBeanNamesForType(TestBean.class, true, true); |
||||
Assert.assertTrue("We should have " + countIncludingFactoryBeans + |
||||
" beans for class org.springframework.beans.TestBean, not " + names.length, |
||||
names.length == countIncludingFactoryBeans); |
||||
} |
||||
|
||||
public void testGetDefinitionsForNoSuchClass() { |
||||
String[] defnames = getListableBeanFactory().getBeanNamesForType(String.class); |
||||
Assert.assertTrue("No string definitions", defnames.length == 0); |
||||
} |
||||
|
||||
/** |
||||
* Check that count refers to factory class, not bean class. (We don't know |
||||
* what type factories may return, and it may even change over time.) |
||||
*/ |
||||
public void testGetCountForFactoryClass() { |
||||
Assert.assertTrue("Should have 2 factories, not " + |
||||
getListableBeanFactory().getBeanNamesForType(FactoryBean.class).length, |
||||
getListableBeanFactory().getBeanNamesForType(FactoryBean.class).length == 2); |
||||
|
||||
Assert.assertTrue("Should have 2 factories, not " + |
||||
getListableBeanFactory().getBeanNamesForType(FactoryBean.class).length, |
||||
getListableBeanFactory().getBeanNamesForType(FactoryBean.class).length == 2); |
||||
} |
||||
|
||||
public void testContainsBeanDefinition() { |
||||
Assert.assertTrue(getListableBeanFactory().containsBeanDefinition("rod")); |
||||
Assert.assertTrue(getListableBeanFactory().containsBeanDefinition("roderick")); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,172 @@
@@ -0,0 +1,172 @@
|
||||
/* |
||||
* Copyright 2002-2007 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; |
||||
|
||||
import org.springframework.beans.BeansException; |
||||
import org.springframework.beans.TestBean; |
||||
import org.springframework.beans.factory.config.AutowireCapableBeanFactory; |
||||
|
||||
/** |
||||
* Simple factory to allow testing of FactoryBean support in AbstractBeanFactory. |
||||
* Depending on whether its singleton property is set, it will return a singleton |
||||
* or a prototype instance. |
||||
* |
||||
* <p>Implements InitializingBean interface, so we can check that |
||||
* factories get this lifecycle callback if they want. |
||||
* |
||||
* @author Rod Johnson |
||||
* @since 10.03.2003 |
||||
*/ |
||||
public class DummyFactory |
||||
implements FactoryBean, BeanNameAware, BeanFactoryAware, InitializingBean, DisposableBean { |
||||
|
||||
public static final String SINGLETON_NAME = "Factory singleton"; |
||||
|
||||
private static boolean prototypeCreated; |
||||
|
||||
/** |
||||
* Clear static state. |
||||
*/ |
||||
public static void reset() { |
||||
prototypeCreated = false; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Default is for factories to return a singleton instance. |
||||
*/ |
||||
private boolean singleton = true; |
||||
|
||||
private String beanName; |
||||
|
||||
private AutowireCapableBeanFactory beanFactory; |
||||
|
||||
private boolean postProcessed; |
||||
|
||||
private boolean initialized; |
||||
|
||||
private TestBean testBean; |
||||
|
||||
private TestBean otherTestBean; |
||||
|
||||
|
||||
public DummyFactory() { |
||||
this.testBean = new TestBean(); |
||||
this.testBean.setName(SINGLETON_NAME); |
||||
this.testBean.setAge(25); |
||||
} |
||||
|
||||
/** |
||||
* Return if the bean managed by this factory is a singleton. |
||||
* @see FactoryBean#isSingleton() |
||||
*/ |
||||
public boolean isSingleton() { |
||||
return this.singleton; |
||||
} |
||||
|
||||
/** |
||||
* Set if the bean managed by this factory is a singleton. |
||||
*/ |
||||
public void setSingleton(boolean singleton) { |
||||
this.singleton = singleton; |
||||
} |
||||
|
||||
public void setBeanName(String beanName) { |
||||
this.beanName = beanName; |
||||
} |
||||
|
||||
public String getBeanName() { |
||||
return beanName; |
||||
} |
||||
|
||||
public void setBeanFactory(BeanFactory beanFactory) { |
||||
this.beanFactory = (AutowireCapableBeanFactory) beanFactory; |
||||
this.beanFactory.applyBeanPostProcessorsBeforeInitialization(this.testBean, this.beanName); |
||||
} |
||||
|
||||
public BeanFactory getBeanFactory() { |
||||
return beanFactory; |
||||
} |
||||
|
||||
public void setPostProcessed(boolean postProcessed) { |
||||
this.postProcessed = postProcessed; |
||||
} |
||||
|
||||
public boolean isPostProcessed() { |
||||
return postProcessed; |
||||
} |
||||
|
||||
public void setOtherTestBean(TestBean otherTestBean) { |
||||
this.otherTestBean = otherTestBean; |
||||
this.testBean.setSpouse(otherTestBean); |
||||
} |
||||
|
||||
public TestBean getOtherTestBean() { |
||||
return otherTestBean; |
||||
} |
||||
|
||||
public void afterPropertiesSet() { |
||||
if (initialized) { |
||||
throw new RuntimeException("Cannot call afterPropertiesSet twice on the one bean"); |
||||
} |
||||
this.initialized = true; |
||||
} |
||||
|
||||
/** |
||||
* Was this initialized by invocation of the |
||||
* afterPropertiesSet() method from the InitializingBean interface? |
||||
*/ |
||||
public boolean wasInitialized() { |
||||
return initialized; |
||||
} |
||||
|
||||
public static boolean wasPrototypeCreated() { |
||||
return prototypeCreated; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Return the managed object, supporting both singleton |
||||
* and prototype mode. |
||||
* @see FactoryBean#getObject() |
||||
*/ |
||||
public Object getObject() throws BeansException { |
||||
if (isSingleton()) { |
||||
return this.testBean; |
||||
} |
||||
else { |
||||
TestBean prototype = new TestBean("prototype created at " + System.currentTimeMillis(), 11); |
||||
if (this.beanFactory != null) { |
||||
this.beanFactory.applyBeanPostProcessorsBeforeInitialization(prototype, this.beanName); |
||||
} |
||||
prototypeCreated = true; |
||||
return prototype; |
||||
} |
||||
} |
||||
|
||||
public Class getObjectType() { |
||||
return TestBean.class; |
||||
} |
||||
|
||||
|
||||
public void destroy() { |
||||
if (this.testBean != null) { |
||||
this.testBean.setName(null); |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,158 @@
@@ -0,0 +1,158 @@
|
||||
/* |
||||
* Copyright 2002-2007 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; |
||||
|
||||
import org.springframework.beans.BeansException; |
||||
import org.springframework.beans.factory.config.BeanPostProcessor; |
||||
|
||||
/** |
||||
* Simple test of BeanFactory initialization and lifecycle callbacks. |
||||
* |
||||
* @author Rod Johnson |
||||
* @author Colin Sampaleanu |
||||
* @since 12.03.2003 |
||||
*/ |
||||
public class LifecycleBean implements BeanNameAware, BeanFactoryAware, InitializingBean, DisposableBean { |
||||
|
||||
protected boolean initMethodDeclared = false; |
||||
|
||||
protected String beanName; |
||||
|
||||
protected BeanFactory owningFactory; |
||||
|
||||
protected boolean postProcessedBeforeInit; |
||||
|
||||
protected boolean inited; |
||||
|
||||
protected boolean initedViaDeclaredInitMethod; |
||||
|
||||
protected boolean postProcessedAfterInit; |
||||
|
||||
protected boolean destroyed; |
||||
|
||||
|
||||
public void setInitMethodDeclared(boolean initMethodDeclared) { |
||||
this.initMethodDeclared = initMethodDeclared; |
||||
} |
||||
|
||||
public boolean isInitMethodDeclared() { |
||||
return initMethodDeclared; |
||||
} |
||||
|
||||
public void setBeanName(String name) { |
||||
this.beanName = name; |
||||
} |
||||
|
||||
public String getBeanName() { |
||||
return beanName; |
||||
} |
||||
|
||||
public void setBeanFactory(BeanFactory beanFactory) { |
||||
this.owningFactory = beanFactory; |
||||
} |
||||
|
||||
public void postProcessBeforeInit() { |
||||
if (this.inited || this.initedViaDeclaredInitMethod) { |
||||
throw new RuntimeException("Factory called postProcessBeforeInit after afterPropertiesSet"); |
||||
} |
||||
if (this.postProcessedBeforeInit) { |
||||
throw new RuntimeException("Factory called postProcessBeforeInit twice"); |
||||
} |
||||
this.postProcessedBeforeInit = true; |
||||
} |
||||
|
||||
public void afterPropertiesSet() { |
||||
if (this.owningFactory == null) { |
||||
throw new RuntimeException("Factory didn't call setBeanFactory before afterPropertiesSet on lifecycle bean"); |
||||
} |
||||
if (!this.postProcessedBeforeInit) { |
||||
throw new RuntimeException("Factory didn't call postProcessBeforeInit before afterPropertiesSet on lifecycle bean"); |
||||
} |
||||
if (this.initedViaDeclaredInitMethod) { |
||||
throw new RuntimeException("Factory initialized via declared init method before initializing via afterPropertiesSet"); |
||||
} |
||||
if (this.inited) { |
||||
throw new RuntimeException("Factory called afterPropertiesSet twice"); |
||||
} |
||||
this.inited = true; |
||||
} |
||||
|
||||
public void declaredInitMethod() { |
||||
if (!this.inited) { |
||||
throw new RuntimeException("Factory didn't call afterPropertiesSet before declared init method"); |
||||
} |
||||
|
||||
if (this.initedViaDeclaredInitMethod) { |
||||
throw new RuntimeException("Factory called declared init method twice"); |
||||
} |
||||
this.initedViaDeclaredInitMethod = true; |
||||
} |
||||
|
||||
public void postProcessAfterInit() { |
||||
if (!this.inited) { |
||||
throw new RuntimeException("Factory called postProcessAfterInit before afterPropertiesSet"); |
||||
} |
||||
if (this.initMethodDeclared && !this.initedViaDeclaredInitMethod) { |
||||
throw new RuntimeException("Factory called postProcessAfterInit before calling declared init method"); |
||||
} |
||||
if (this.postProcessedAfterInit) { |
||||
throw new RuntimeException("Factory called postProcessAfterInit twice"); |
||||
} |
||||
this.postProcessedAfterInit = true; |
||||
} |
||||
|
||||
/** |
||||
* Dummy business method that will fail unless the factory |
||||
* managed the bean's lifecycle correctly |
||||
*/ |
||||
public void businessMethod() { |
||||
if (!this.inited || (this.initMethodDeclared && !this.initedViaDeclaredInitMethod) || |
||||
!this.postProcessedAfterInit) { |
||||
throw new RuntimeException("Factory didn't initialize lifecycle object correctly"); |
||||
} |
||||
} |
||||
|
||||
public void destroy() { |
||||
if (this.destroyed) { |
||||
throw new IllegalStateException("Already destroyed"); |
||||
} |
||||
this.destroyed = true; |
||||
} |
||||
|
||||
public boolean isDestroyed() { |
||||
return destroyed; |
||||
} |
||||
|
||||
|
||||
public static class PostProcessor implements BeanPostProcessor { |
||||
|
||||
public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException { |
||||
if (bean instanceof LifecycleBean) { |
||||
((LifecycleBean) bean).postProcessBeforeInit(); |
||||
} |
||||
return bean; |
||||
} |
||||
|
||||
public Object postProcessAfterInitialization(Object bean, String name) throws BeansException { |
||||
if (bean instanceof LifecycleBean) { |
||||
((LifecycleBean) bean).postProcessAfterInit(); |
||||
} |
||||
return bean; |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,44 @@
@@ -0,0 +1,44 @@
|
||||
/* |
||||
* Copyright 2002-2005 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; |
||||
|
||||
/** |
||||
* Simple test of BeanFactory initialization |
||||
* @author Rod Johnson |
||||
* @since 12.03.2003 |
||||
*/ |
||||
public class MustBeInitialized implements InitializingBean { |
||||
|
||||
private boolean inited; |
||||
|
||||
/** |
||||
* @see InitializingBean#afterPropertiesSet() |
||||
*/ |
||||
public void afterPropertiesSet() throws Exception { |
||||
this.inited = true; |
||||
} |
||||
|
||||
/** |
||||
* Dummy business method that will fail unless the factory |
||||
* managed the bean's lifecycle correctly |
||||
*/ |
||||
public void businessMethod() { |
||||
if (!this.inited) |
||||
throw new RuntimeException("Factory didn't call afterPropertiesSet() on MustBeInitialized object"); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,66 @@
@@ -0,0 +1,66 @@
|
||||
/* |
||||
* Copyright 2002-2005 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 org.springframework.beans.TestBean; |
||||
import org.springframework.beans.factory.DummyFactory; |
||||
|
||||
/** |
||||
* @author Juergen Hoeller |
||||
* @since 21.07.2003 |
||||
*/ |
||||
public class DummyReferencer { |
||||
|
||||
private TestBean testBean1; |
||||
|
||||
private TestBean testBean2; |
||||
|
||||
private DummyFactory dummyFactory; |
||||
|
||||
|
||||
public DummyReferencer() { |
||||
} |
||||
|
||||
public DummyReferencer(DummyFactory dummyFactory) { |
||||
this.dummyFactory = dummyFactory; |
||||
} |
||||
|
||||
public void setDummyFactory(DummyFactory dummyFactory) { |
||||
this.dummyFactory = dummyFactory; |
||||
} |
||||
|
||||
public DummyFactory getDummyFactory() { |
||||
return dummyFactory; |
||||
} |
||||
|
||||
public void setTestBean1(TestBean testBean1) { |
||||
this.testBean1 = testBean1; |
||||
} |
||||
|
||||
public TestBean getTestBean1() { |
||||
return testBean1; |
||||
} |
||||
|
||||
public void setTestBean2(TestBean testBean2) { |
||||
this.testBean2 = testBean2; |
||||
} |
||||
|
||||
public TestBean getTestBean2() { |
||||
return testBean2; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,162 @@
@@ -0,0 +1,162 @@
|
||||
/* |
||||
* Copyright 2002-2007 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 org.springframework.beans.BeansException; |
||||
import org.springframework.beans.factory.BeanFactory; |
||||
import org.springframework.beans.factory.BeanFactoryAware; |
||||
import org.springframework.beans.factory.BeanNameAware; |
||||
import org.springframework.beans.factory.DisposableBean; |
||||
import org.springframework.beans.factory.InitializingBean; |
||||
import org.springframework.beans.factory.config.BeanPostProcessor; |
||||
|
||||
/** |
||||
* Simple test of BeanFactory initialization and lifecycle callbacks. |
||||
* |
||||
* @author Rod Johnson |
||||
* @author Juergen Hoeller |
||||
*/ |
||||
class ProtectedLifecycleBean implements BeanNameAware, BeanFactoryAware, InitializingBean, DisposableBean { |
||||
|
||||
protected boolean initMethodDeclared = false; |
||||
|
||||
protected String beanName; |
||||
|
||||
protected BeanFactory owningFactory; |
||||
|
||||
protected boolean postProcessedBeforeInit; |
||||
|
||||
protected boolean inited; |
||||
|
||||
protected boolean initedViaDeclaredInitMethod; |
||||
|
||||
protected boolean postProcessedAfterInit; |
||||
|
||||
protected boolean destroyed; |
||||
|
||||
|
||||
public void setInitMethodDeclared(boolean initMethodDeclared) { |
||||
this.initMethodDeclared = initMethodDeclared; |
||||
} |
||||
|
||||
public boolean isInitMethodDeclared() { |
||||
return initMethodDeclared; |
||||
} |
||||
|
||||
public void setBeanName(String name) { |
||||
this.beanName = name; |
||||
} |
||||
|
||||
public String getBeanName() { |
||||
return beanName; |
||||
} |
||||
|
||||
public void setBeanFactory(BeanFactory beanFactory) { |
||||
this.owningFactory = beanFactory; |
||||
} |
||||
|
||||
public void postProcessBeforeInit() { |
||||
if (this.inited || this.initedViaDeclaredInitMethod) { |
||||
throw new RuntimeException("Factory called postProcessBeforeInit after afterPropertiesSet"); |
||||
} |
||||
if (this.postProcessedBeforeInit) { |
||||
throw new RuntimeException("Factory called postProcessBeforeInit twice"); |
||||
} |
||||
this.postProcessedBeforeInit = true; |
||||
} |
||||
|
||||
public void afterPropertiesSet() { |
||||
if (this.owningFactory == null) { |
||||
throw new RuntimeException("Factory didn't call setBeanFactory before afterPropertiesSet on lifecycle bean"); |
||||
} |
||||
if (!this.postProcessedBeforeInit) { |
||||
throw new RuntimeException("Factory didn't call postProcessBeforeInit before afterPropertiesSet on lifecycle bean"); |
||||
} |
||||
if (this.initedViaDeclaredInitMethod) { |
||||
throw new RuntimeException("Factory initialized via declared init method before initializing via afterPropertiesSet"); |
||||
} |
||||
if (this.inited) { |
||||
throw new RuntimeException("Factory called afterPropertiesSet twice"); |
||||
} |
||||
this.inited = true; |
||||
} |
||||
|
||||
public void declaredInitMethod() { |
||||
if (!this.inited) { |
||||
throw new RuntimeException("Factory didn't call afterPropertiesSet before declared init method"); |
||||
} |
||||
|
||||
if (this.initedViaDeclaredInitMethod) { |
||||
throw new RuntimeException("Factory called declared init method twice"); |
||||
} |
||||
this.initedViaDeclaredInitMethod = true; |
||||
} |
||||
|
||||
public void postProcessAfterInit() { |
||||
if (!this.inited) { |
||||
throw new RuntimeException("Factory called postProcessAfterInit before afterPropertiesSet"); |
||||
} |
||||
if (this.initMethodDeclared && !this.initedViaDeclaredInitMethod) { |
||||
throw new RuntimeException("Factory called postProcessAfterInit before calling declared init method"); |
||||
} |
||||
if (this.postProcessedAfterInit) { |
||||
throw new RuntimeException("Factory called postProcessAfterInit twice"); |
||||
} |
||||
this.postProcessedAfterInit = true; |
||||
} |
||||
|
||||
/** |
||||
* Dummy business method that will fail unless the factory |
||||
* managed the bean's lifecycle correctly |
||||
*/ |
||||
public void businessMethod() { |
||||
if (!this.inited || (this.initMethodDeclared && !this.initedViaDeclaredInitMethod) || |
||||
!this.postProcessedAfterInit) { |
||||
throw new RuntimeException("Factory didn't initialize lifecycle object correctly"); |
||||
} |
||||
} |
||||
|
||||
public void destroy() { |
||||
if (this.destroyed) { |
||||
throw new IllegalStateException("Already destroyed"); |
||||
} |
||||
this.destroyed = true; |
||||
} |
||||
|
||||
public boolean isDestroyed() { |
||||
return destroyed; |
||||
} |
||||
|
||||
|
||||
public static class PostProcessor implements BeanPostProcessor { |
||||
|
||||
public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException { |
||||
if (bean instanceof ProtectedLifecycleBean) { |
||||
((ProtectedLifecycleBean) bean).postProcessBeforeInit(); |
||||
} |
||||
return bean; |
||||
} |
||||
|
||||
public Object postProcessAfterInitialization(Object bean, String name) throws BeansException { |
||||
if (bean instanceof ProtectedLifecycleBean) { |
||||
((ProtectedLifecycleBean) bean).postProcessAfterInit(); |
||||
} |
||||
return bean; |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,127 @@
@@ -0,0 +1,127 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd"> |
||||
|
||||
<beans> |
||||
|
||||
<bean id="validEmptyWithDescription" class="org.springframework.beans.TestBean"> |
||||
<description> |
||||
I have no properties and I'm happy without them. |
||||
</description> |
||||
</bean> |
||||
|
||||
<!-- |
||||
Check automatic creation of alias, to allow for names that are illegal as XML ids. |
||||
--> |
||||
<bean id="aliased" class=" org.springframework.beans.TestBean " name="myalias"> |
||||
<property name="name"><value>aliased</value></property> |
||||
</bean> |
||||
|
||||
<alias name="aliased" alias="youralias"/> |
||||
|
||||
<alias name="multiAliased" alias="alias3"/> |
||||
|
||||
<bean id="multiAliased" class="org.springframework.beans.TestBean" name="alias1,alias2"> |
||||
<property name="name"><value>aliased</value></property> |
||||
</bean> |
||||
|
||||
<alias name="multiAliased" alias="alias4"/> |
||||
|
||||
<bean class="org.springframework.beans.TestBean" name="aliasWithoutId1,aliasWithoutId2,aliasWithoutId3"> |
||||
<property name="name"><value>aliased</value></property> |
||||
</bean> |
||||
|
||||
<bean class="org.springframework.beans.TestBean"> |
||||
<property name="name"><null/></property> |
||||
</bean> |
||||
|
||||
<bean class="org.springframework.beans.factory.xml.DummyReferencer"/> |
||||
|
||||
<bean class="org.springframework.beans.factory.xml.DummyReferencer"/> |
||||
|
||||
<bean class="org.springframework.beans.factory.xml.DummyReferencer"/> |
||||
|
||||
<bean id="rod" class="org.springframework.beans.TestBean"> |
||||
<property name="name"><value><!-- a comment -->Rod</value></property> |
||||
<property name="age"><value>31</value></property> |
||||
<property name="spouse"><ref bean="father"/></property> |
||||
<property name="touchy"><value/></property> |
||||
</bean> |
||||
|
||||
<bean id="roderick" parent="rod"> |
||||
<property name="name"><value>Roderick<!-- a comment --></value></property> |
||||
<!-- Should inherit age --> |
||||
</bean> |
||||
|
||||
<bean id="kerry" class="org.springframework.beans.TestBean"> |
||||
<property name="name"><value>Ker<!-- a comment -->ry</value></property> |
||||
<property name="age"><value>34</value></property> |
||||
<property name="spouse"><ref local="rod"/></property> |
||||
<property name="touchy"><value></value></property> |
||||
</bean> |
||||
|
||||
<bean id="kathy" class="org.springframework.beans.TestBean" scope="prototype"> |
||||
<property name="name"><value>Kathy</value></property> |
||||
<property name="age"><value>28</value></property> |
||||
<property name="spouse"><ref bean="father"/></property> |
||||
</bean> |
||||
|
||||
<bean id="typeMismatch" class="org.springframework.beans.TestBean" scope="prototype"> |
||||
<property name="name"><value>typeMismatch</value></property> |
||||
<property name="age"><value>34x</value></property> |
||||
<property name="spouse"><ref local="rod"/></property> |
||||
</bean> |
||||
|
||||
<!-- Test of lifecycle callbacks --> |
||||
<bean id="mustBeInitialized" class="org.springframework.beans.factory.MustBeInitialized"/> |
||||
|
||||
<bean id="lifecycle" class="org.springframework.beans.factory.LifecycleBean" |
||||
init-method="declaredInitMethod"> |
||||
<property name="initMethodDeclared"><value>true</value></property> |
||||
</bean> |
||||
|
||||
<bean id="protectedLifecycle" class="org.springframework.beans.factory.xml.ProtectedLifecycleBean" |
||||
init-method="declaredInitMethod"> |
||||
<property name="initMethodDeclared"><value>true</value></property> |
||||
</bean> |
||||
|
||||
<!-- Factory beans are automatically treated differently --> |
||||
<bean id="singletonFactory" class="org.springframework.beans.factory.DummyFactory"> |
||||
</bean> |
||||
|
||||
<bean id="prototypeFactory" class="org.springframework.beans.factory.DummyFactory"> |
||||
<property name="singleton"><value>false</value></property> |
||||
</bean> |
||||
|
||||
<!-- Check that the circular reference resolution mechanism doesn't break |
||||
repeated references to the same FactoryBean --> |
||||
<bean id="factoryReferencer" class="org.springframework.beans.factory.xml.DummyReferencer"> |
||||
<property name="testBean1"><ref bean="singletonFactory"/></property> |
||||
<property name="testBean2"><ref local="singletonFactory"/></property> |
||||
<property name="dummyFactory"><ref bean="&singletonFactory"/></property> |
||||
</bean> |
||||
|
||||
<bean id="factoryReferencerWithConstructor" class="org.springframework.beans.factory.xml.DummyReferencer"> |
||||
<constructor-arg><ref bean="&singletonFactory"/></constructor-arg> |
||||
<property name="testBean1"><ref bean="singletonFactory"/></property> |
||||
<property name="testBean2"><ref local="singletonFactory"/></property> |
||||
</bean> |
||||
|
||||
<!-- Check that the circular reference resolution mechanism doesn't break |
||||
prototype instantiation --> |
||||
<bean id="prototypeReferencer" class="org.springframework.beans.factory.xml.DummyReferencer" scope="prototype"> |
||||
<property name="testBean1"><ref local="kathy"/></property> |
||||
<property name="testBean2"><ref bean="kathy"/></property> |
||||
</bean> |
||||
|
||||
<bean id="listenerVeto" class="org.springframework.beans.TestBean"> |
||||
<property name="name"><value>listenerVeto</value></property> |
||||
<property name="age"><value>66</value></property> |
||||
</bean> |
||||
|
||||
<bean id="validEmpty" class="org.springframework.beans.TestBean"/> |
||||
|
||||
<bean id="commentsInValue" class="org.springframework.beans.TestBean"> |
||||
<property name="name"><value>this is<!-- don't mind me --> a <![CDATA[<!--comment-->]]></value></property> |
||||
</bean> |
||||
|
||||
</beans> |
||||
@ -0,0 +1,13 @@
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!-- |
||||
This is a top level block comment |
||||
--> |
||||
<!-- here is a line comment --> |
||||
<!-- trying --> <!-- to trick --> <!-- |
||||
the parser now --> <!-- <beans> |
||||
--> |
||||
<!-- more trickery--> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd"><!-- some nasty stuff --> |
||||
|
||||
<beans> |
||||
<bean id="testBean" class="org.springframework.beans.TestBean"/> |
||||
</beans> |
||||
@ -0,0 +1,11 @@
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!-- |
||||
This is a top level block comment |
||||
--> |
||||
<!-- here is a line comment --> |
||||
<!-- trying --> <!-- to trick --> <!-- |
||||
the parser now --> <!-- <beans> |
||||
--> |
||||
<!-- more trickery--><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-2.0.xsd"><!-- end --> |
||||
<bean id="testBean" class="org.springframework.beans.TestBean"/> |
||||
</beans> |
||||
Loading…
Reference in new issue