View Javadoc
1   /*
2    * Copyright 2002-2014 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springframework.beans.factory.xml;
18  
19  import java.beans.ConstructorProperties;
20  import java.io.Serializable;
21  import java.lang.reflect.Method;
22  import java.util.Collection;
23  import java.util.Collections;
24  import java.util.List;
25  import java.util.Map;
26  import java.util.Set;
27  import javax.sql.DataSource;
28  
29  import org.springframework.beans.BeansException;
30  import org.springframework.beans.factory.BeanFactory;
31  import org.springframework.beans.factory.BeanFactoryAware;
32  import org.springframework.beans.factory.BeanNameAware;
33  import org.springframework.beans.factory.DisposableBean;
34  import org.springframework.beans.factory.InitializingBean;
35  import org.springframework.beans.factory.config.BeanPostProcessor;
36  import org.springframework.beans.factory.support.MethodReplacer;
37  import org.springframework.tests.sample.beans.ITestBean;
38  import org.springframework.tests.sample.beans.IndexedTestBean;
39  import org.springframework.tests.sample.beans.TestBean;
40  import org.springframework.tests.sample.beans.factory.DummyFactory;
41  
42  /**
43   * Types used by {@link XmlBeanFactoryTests} and its attendant XML config files.
44   *
45   * @author Chris Beams
46   */
47  final class XmlBeanFactoryTestTypes {
48  }
49  
50  
51  /**
52   * Simple bean used to check constructor dependency checking.
53   *
54   * @author Juergen Hoeller
55   * @since 09.11.2003
56   */
57  @SuppressWarnings("serial")
58  class ConstructorDependenciesBean implements Serializable {
59  
60  	private int age;
61  
62  	private String name;
63  
64  	private TestBean spouse1;
65  
66  	private TestBean spouse2;
67  
68  	private IndexedTestBean other;
69  
70  	public ConstructorDependenciesBean(int age) {
71  		this.age = age;
72  	}
73  
74  	public ConstructorDependenciesBean(String name) {
75  		this.name = name;
76  	}
77  
78  	public ConstructorDependenciesBean(TestBean spouse1) {
79  		this.spouse1 = spouse1;
80  	}
81  
82  	public ConstructorDependenciesBean(TestBean spouse1, TestBean spouse2) {
83  		this.spouse1 = spouse1;
84  		this.spouse2 = spouse2;
85  	}
86  
87  	@ConstructorProperties({"spouse", "otherSpouse", "myAge"})
88  	public ConstructorDependenciesBean(TestBean spouse1, TestBean spouse2, int age) {
89  		this.spouse1 = spouse1;
90  		this.spouse2 = spouse2;
91  		this.age = age;
92  	}
93  
94  	public ConstructorDependenciesBean(TestBean spouse1, TestBean spouse2, IndexedTestBean other) {
95  		this.spouse1 = spouse1;
96  		this.spouse2 = spouse2;
97  		this.other = other;
98  	}
99  
100 	public int getAge() {
101 		return age;
102 	}
103 
104 	public String getName() {
105 		return name;
106 	}
107 
108 	public TestBean getSpouse1() {
109 		return spouse1;
110 	}
111 
112 	public TestBean getSpouse2() {
113 		return spouse2;
114 	}
115 
116 	public IndexedTestBean getOther() {
117 		return other;
118 	}
119 
120 	public void setAge(int age) {
121 		this.age = age;
122 	}
123 
124 	public void setName(String name) {
125 		this.name = name;
126 	}
127 }
128 
129 
130 class SimpleConstructorArgBean {
131 
132 	private int age;
133 
134 	private String name;
135 
136 	public SimpleConstructorArgBean() {
137 	}
138 
139 	public SimpleConstructorArgBean(int age) {
140 		this.age = age;
141 	}
142 
143 	public SimpleConstructorArgBean(String name) {
144 		this.name = name;
145 	}
146 
147 	public int getAge() {
148 		return age;
149 	}
150 
151 	public String getName() {
152 		return name;
153 	}
154 }
155 
156 
157 /**
158  * Bean testing the ability to use both lookup method overrides
159  * and constructor injection.
160  * There is also a property ("setterString") to be set via
161  * Setter Injection.
162  *
163  * @author Rod Johnson
164  */
165 abstract class ConstructorInjectedOverrides {
166 
167 	private ITestBean tb;
168 
169 	private String setterString;
170 
171 	public ConstructorInjectedOverrides(ITestBean tb) {
172 		this.tb = tb;
173 	}
174 
175 	public ITestBean getTestBean() {
176 		return this.tb;
177 	}
178 
179 	protected abstract FactoryMethods createFactoryMethods();
180 
181 	public String getSetterString() {
182 		return setterString;
183 	}
184 
185 	public void setSetterString(String setterString) {
186 		this.setterString = setterString;
187 	}
188 }
189 
190 
191 /**
192  * Simple bean used to check constructor dependency checking.
193  *
194  * @author Juergen Hoeller
195  * @since 09.11.2003
196  */
197 @SuppressWarnings({ "serial", "unused" })
198 class DerivedConstructorDependenciesBean extends ConstructorDependenciesBean {
199 
200 	boolean initialized;
201 	boolean destroyed;
202 
203 	DerivedConstructorDependenciesBean(TestBean spouse1, TestBean spouse2, IndexedTestBean other) {
204 		super(spouse1, spouse2, other);
205 	}
206 
207 	private DerivedConstructorDependenciesBean(TestBean spouse1, Object spouse2, IndexedTestBean other) {
208 		super(spouse1, null, other);
209 	}
210 
211 	protected DerivedConstructorDependenciesBean(TestBean spouse1, TestBean spouse2, IndexedTestBean other, int age, int otherAge) {
212 		super(spouse1, spouse2, other);
213 	}
214 
215 	public DerivedConstructorDependenciesBean(TestBean spouse1, TestBean spouse2, IndexedTestBean other, int age, String name) {
216 		super(spouse1, spouse2, other);
217 		setAge(age);
218 		setName(name);
219 	}
220 
221 	private void init() {
222 		this.initialized = true;
223 	}
224 
225 	private void destroy() {
226 		this.destroyed = true;
227 	}
228 }
229 
230 
231 /**
232  *
233  * @author Rod Johnson
234  */
235 interface DummyBo {
236 
237 	void something();
238 }
239 
240 
241 /**
242  *
243  * @author Rod Johnson
244  */
245 class DummyBoImpl implements DummyBo {
246 
247 	DummyDao dao;
248 
249 	public DummyBoImpl(DummyDao dao) {
250 		this.dao = dao;
251 	}
252 
253 	@Override
254 	public void something() {
255 	}
256 }
257 
258 
259 /**
260  * @author Rod Johnson
261  */
262 class DummyDao {
263 
264 	DataSource ds;
265 
266 	public DummyDao(DataSource ds) {
267 		this.ds = ds;
268 	}
269 }
270 
271 
272 /**
273  * @author Juergen Hoeller
274  * @since 21.07.2003
275  */
276 class DummyReferencer {
277 
278 	private TestBean testBean1;
279 
280 	private TestBean testBean2;
281 
282 	private DummyFactory dummyFactory;
283 
284 	public DummyReferencer() {
285 	}
286 
287 	public DummyReferencer(DummyFactory dummyFactory) {
288 		this.dummyFactory = dummyFactory;
289 	}
290 
291 	public void setDummyFactory(DummyFactory dummyFactory) {
292 		this.dummyFactory = dummyFactory;
293 	}
294 
295 	public DummyFactory getDummyFactory() {
296 		return dummyFactory;
297 	}
298 
299 	public void setTestBean1(TestBean testBean1) {
300 		this.testBean1 = testBean1;
301 	}
302 
303 	public TestBean getTestBean1() {
304 		return testBean1;
305 	}
306 
307 	public void setTestBean2(TestBean testBean2) {
308 		this.testBean2 = testBean2;
309 	}
310 
311 	public TestBean getTestBean2() {
312 		return testBean2;
313 	}
314 }
315 
316 
317 /**
318  * Test class for Spring's ability to create objects using static
319  * factory methods, rather than constructors.
320  *
321  * @author Rod Johnson
322  * @author Juergen Hoeller
323  */
324 @SuppressWarnings("unused")
325 class FactoryMethods {
326 
327 	public static FactoryMethods nullInstance() {
328 		return null;
329 	}
330 
331 	public static FactoryMethods defaultInstance() {
332 		TestBean tb = new TestBean();
333 		tb.setName("defaultInstance");
334 		return new FactoryMethods(tb, "default", 0);
335 	}
336 
337 	/**
338 	 * Note that overloaded methods are supported.
339 	 */
340 	public static FactoryMethods newInstance(TestBean tb) {
341 		return new FactoryMethods(tb, "default", 0);
342 	}
343 
344 	protected static FactoryMethods newInstance(TestBean tb, int num, String name) {
345 		if (name == null) {
346 			throw new IllegalStateException("Should never be called with null value");
347 		}
348 		return new FactoryMethods(tb, name, num);
349 	}
350 
351 	static FactoryMethods newInstance(TestBean tb, int num, Integer something) {
352 		if (something != null) {
353 			throw new IllegalStateException("Should never be called with non-null value");
354 		}
355 		return new FactoryMethods(tb, null, num);
356 	}
357 
358 	private static List<?> listInstance() {
359 		return Collections.EMPTY_LIST;
360 	}
361 
362 	private int num = 0;
363 	private String name = "default";
364 	private TestBean tb;
365 	private String stringValue;
366 
367 	/**
368 	 * Constructor is private: not for use outside this class,
369 	 * even by IoC container.
370 	 */
371 	private FactoryMethods(TestBean tb, String name, int num) {
372 		this.tb = tb;
373 		this.name = name;
374 		this.num = num;
375 	}
376 
377 	public void setStringValue(String stringValue) {
378 		this.stringValue = stringValue;
379 	}
380 
381 	public String getStringValue() {
382 		return this.stringValue;
383 	}
384 
385 	public TestBean getTestBean() {
386 		return this.tb;
387 	}
388 
389 	protected TestBean protectedGetTestBean() {
390 		return this.tb;
391 	}
392 
393 	private TestBean privateGetTestBean() {
394 		return this.tb;
395 	}
396 
397 	public int getNum() {
398 		return num;
399 	}
400 
401 	public String getName() {
402 		return name;
403 	}
404 
405 	/**
406 	 * Set via Setter Injection once instance is created.
407 	 */
408 	public void setName(String name) {
409 		this.name = name;
410 	}
411 }
412 
413 /**
414  * Fixed method replacer for String return types
415  * @author Rod Johnson
416  */
417 class FixedMethodReplacer implements MethodReplacer {
418 
419 	public static final String VALUE = "fixedMethodReplacer";
420 
421 	@Override
422 	public Object reimplement(Object obj, Method method, Object[] args) throws Throwable {
423 		return VALUE;
424 	}
425 }
426 
427 
428 /**
429  * @author Chris Beams
430  */
431 class MapAndSet {
432 
433 	private Object obj;
434 
435 	public MapAndSet(Map<?, ?> map) {
436 		this.obj = map;
437 	}
438 
439 	public MapAndSet(Set<?> set) {
440 		this.obj = set;
441 	}
442 
443 	public Object getObject() {
444 		return obj;
445 	}
446 }
447 
448 
449 /**
450  * @author Rod Johnson
451  */
452 class MethodReplaceCandidate {
453 
454 	public String replaceMe(String echo) {
455 		return echo;
456 	}
457 }
458 
459 
460 /**
461  * Bean that exposes a simple property that can be set
462  * to a mix of references and individual values.
463  */
464 class MixedCollectionBean {
465 
466 	private Collection<?> jumble;
467 
468 	public void setJumble(Collection<?> jumble) {
469 		this.jumble = jumble;
470 	}
471 
472 	public Collection<?> getJumble() {
473 		return jumble;
474 	}
475 }
476 
477 
478 /**
479  * @author Juergen Hoeller
480  */
481 interface OverrideInterface {
482 
483 	TestBean getPrototypeDependency();
484 
485 	TestBean getPrototypeDependency(Object someParam);
486 }
487 
488 
489 /**
490  * @author Rod Johnson
491  * @author Juergen Hoeller
492  */
493 abstract class OverrideOneMethod extends MethodReplaceCandidate implements OverrideInterface {
494 
495 	protected abstract TestBean protectedOverrideSingleton();
496 
497 	@Override
498 	public TestBean getPrototypeDependency(Object someParam) {
499 		return new TestBean();
500 	}
501 
502 	public TestBean invokesOverriddenMethodOnSelf() {
503 		return getPrototypeDependency();
504 	}
505 
506 	public String echo(String echo) {
507 		return echo;
508 	}
509 
510 	/**
511 	 * Overloaded form of replaceMe.
512 	 */
513 	public String replaceMe() {
514 		return "replaceMe";
515 	}
516 
517 	/**
518 	 * Another overloaded form of replaceMe, not getting replaced.
519 	 * Must not cause errors when the other replaceMe methods get replaced.
520 	 */
521 	public String replaceMe(int someParam) {
522 		return "replaceMe:" + someParam;
523 	}
524 
525 	@Override
526 	public String replaceMe(String someParam) {
527 		return "replaceMe:"  + someParam;
528 	}
529 }
530 
531 
532 /**
533  * Subclass of OverrideOneMethod, to check that overriding is
534  * supported for inherited methods.
535  *
536  * @author Rod Johnson
537  */
538 abstract class OverrideOneMethodSubclass extends OverrideOneMethod {
539 
540 	protected void doSomething(String arg) {
541 		// This implementation does nothing!
542 		// It's not overloaded
543 	}
544 }
545 
546 
547 /**
548  * Simple test of BeanFactory initialization and lifecycle callbacks.
549  *
550  * @author Rod Johnson
551  * @author Juergen Hoeller
552  */
553 class ProtectedLifecycleBean implements BeanNameAware, BeanFactoryAware, InitializingBean, DisposableBean {
554 
555 	protected boolean initMethodDeclared = false;
556 
557 	protected String beanName;
558 
559 	protected BeanFactory owningFactory;
560 
561 	protected boolean postProcessedBeforeInit;
562 
563 	protected boolean inited;
564 
565 	protected boolean initedViaDeclaredInitMethod;
566 
567 	protected boolean postProcessedAfterInit;
568 
569 	protected boolean destroyed;
570 
571 	public void setInitMethodDeclared(boolean initMethodDeclared) {
572 		this.initMethodDeclared = initMethodDeclared;
573 	}
574 
575 	public boolean isInitMethodDeclared() {
576 		return initMethodDeclared;
577 	}
578 
579 	@Override
580 	public void setBeanName(String name) {
581 		this.beanName = name;
582 	}
583 
584 	public String getBeanName() {
585 		return beanName;
586 	}
587 
588 	@Override
589 	public void setBeanFactory(BeanFactory beanFactory) {
590 		this.owningFactory = beanFactory;
591 	}
592 
593 	public void postProcessBeforeInit() {
594 		if (this.inited || this.initedViaDeclaredInitMethod) {
595 			throw new RuntimeException("Factory called postProcessBeforeInit after afterPropertiesSet");
596 		}
597 		if (this.postProcessedBeforeInit) {
598 			throw new RuntimeException("Factory called postProcessBeforeInit twice");
599 		}
600 		this.postProcessedBeforeInit = true;
601 	}
602 
603 	@Override
604 	public void afterPropertiesSet() {
605 		if (this.owningFactory == null) {
606 			throw new RuntimeException("Factory didn't call setBeanFactory before afterPropertiesSet on lifecycle bean");
607 		}
608 		if (!this.postProcessedBeforeInit) {
609 			throw new RuntimeException("Factory didn't call postProcessBeforeInit before afterPropertiesSet on lifecycle bean");
610 		}
611 		if (this.initedViaDeclaredInitMethod) {
612 			throw new RuntimeException("Factory initialized via declared init method before initializing via afterPropertiesSet");
613 		}
614 		if (this.inited) {
615 			throw new RuntimeException("Factory called afterPropertiesSet twice");
616 		}
617 		this.inited = true;
618 	}
619 
620 	public void declaredInitMethod() {
621 		if (!this.inited) {
622 			throw new RuntimeException("Factory didn't call afterPropertiesSet before declared init method");
623 		}
624 
625 		if (this.initedViaDeclaredInitMethod) {
626 			throw new RuntimeException("Factory called declared init method twice");
627 		}
628 		this.initedViaDeclaredInitMethod = true;
629 	}
630 
631 	public void postProcessAfterInit() {
632 		if (!this.inited) {
633 			throw new RuntimeException("Factory called postProcessAfterInit before afterPropertiesSet");
634 		}
635 		if (this.initMethodDeclared && !this.initedViaDeclaredInitMethod) {
636 			throw new RuntimeException("Factory called postProcessAfterInit before calling declared init method");
637 		}
638 		if (this.postProcessedAfterInit) {
639 			throw new RuntimeException("Factory called postProcessAfterInit twice");
640 		}
641 		this.postProcessedAfterInit = true;
642 	}
643 
644 	/**
645 	 * Dummy business method that will fail unless the factory
646 	 * managed the bean's lifecycle correctly
647 	 */
648 	public void businessMethod() {
649 		if (!this.inited || (this.initMethodDeclared && !this.initedViaDeclaredInitMethod) ||
650 				!this.postProcessedAfterInit) {
651 			throw new RuntimeException("Factory didn't initialize lifecycle object correctly");
652 		}
653 	}
654 
655 	@Override
656 	public void destroy() {
657 		if (this.destroyed) {
658 			throw new IllegalStateException("Already destroyed");
659 		}
660 		this.destroyed = true;
661 	}
662 
663 	public boolean isDestroyed() {
664 		return destroyed;
665 	}
666 
667 
668 	public static class PostProcessor implements BeanPostProcessor {
669 
670 		@Override
671 		public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException {
672 			if (bean instanceof ProtectedLifecycleBean) {
673 				((ProtectedLifecycleBean) bean).postProcessBeforeInit();
674 			}
675 			return bean;
676 		}
677 
678 		@Override
679 		public Object postProcessAfterInitialization(Object bean, String name) throws BeansException {
680 			if (bean instanceof ProtectedLifecycleBean) {
681 				((ProtectedLifecycleBean) bean).postProcessAfterInit();
682 			}
683 			return bean;
684 		}
685 	}
686 }
687 
688 
689 /**
690  * @author Rod Johnson
691  */
692 @SuppressWarnings("serial")
693 class ReverseMethodReplacer implements MethodReplacer, Serializable {
694 
695 	@Override
696 	public Object reimplement(Object obj, Method method, Object[] args) throws Throwable {
697 		String s = (String) args[0];
698 		return new StringBuffer(s).reverse().toString();
699 	}
700 }
701 
702 
703 /**
704  * @author Rod Johnson
705  */
706 @SuppressWarnings("serial")
707 abstract class SerializableMethodReplacerCandidate extends MethodReplaceCandidate implements Serializable {
708 
709 	//public abstract Point getPoint();
710 }
711 
712 
713 /**
714  * @author Juergen Hoeller
715  * @since 23.10.2004
716  */
717 class SingleSimpleTypeConstructorBean {
718 
719 	private boolean singleBoolean;
720 
721 	private boolean secondBoolean;
722 
723 	private String testString;
724 
725 	public SingleSimpleTypeConstructorBean(boolean singleBoolean) {
726 		this.singleBoolean = singleBoolean;
727 	}
728 
729 	protected SingleSimpleTypeConstructorBean(String testString, boolean secondBoolean) {
730 		this.testString = testString;
731 		this.secondBoolean = secondBoolean;
732 	}
733 
734 	public boolean isSingleBoolean() {
735 		return singleBoolean;
736 	}
737 
738 	public boolean isSecondBoolean() {
739 		return secondBoolean;
740 	}
741 
742 	public String getTestString() {
743 		return testString;
744 	}
745 }