1 /*
2 * Copyright 2002-2008 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.support;
18
19 import java.lang.reflect.Constructor;
20 import java.util.Arrays;
21 import java.util.Iterator;
22 import java.util.LinkedHashMap;
23 import java.util.LinkedHashSet;
24 import java.util.Map;
25 import java.util.Set;
26
27 import org.springframework.beans.BeanMetadataAttributeAccessor;
28 import org.springframework.beans.MutablePropertyValues;
29 import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
30 import org.springframework.beans.factory.config.BeanDefinition;
31 import org.springframework.beans.factory.config.ConstructorArgumentValues;
32 import org.springframework.core.io.DescriptiveResource;
33 import org.springframework.core.io.Resource;
34 import org.springframework.util.Assert;
35 import org.springframework.util.ClassUtils;
36 import org.springframework.util.ObjectUtils;
37
38 /**
39 * Base class for concrete, full-fledged
40 * {@link org.springframework.beans.factory.config.BeanDefinition} classes,
41 * factoring out common properties of {@link RootBeanDefinition} and
42 * {@link ChildBeanDefinition}.
43 *
44 * <p>The autowire constants match the ones defined in the
45 * {@link org.springframework.beans.factory.config.AutowireCapableBeanFactory}
46 * interface.
47 *
48 * @author Rod Johnson
49 * @author Juergen Hoeller
50 * @author Rob Harrop
51 * @author Mark Fisher
52 * @see RootBeanDefinition
53 * @see ChildBeanDefinition
54 */
55 public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
56 implements BeanDefinition, Cloneable {
57
58 /**
59 * Constant that indicates no autowiring at all.
60 * @see #setAutowireMode
61 */
62 public static final int AUTOWIRE_NO = AutowireCapableBeanFactory.AUTOWIRE_NO;
63
64 /**
65 * Constant that indicates autowiring bean properties by name.
66 * @see #setAutowireMode
67 */
68 public static final int AUTOWIRE_BY_NAME = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME;
69
70 /**
71 * Constant that indicates autowiring bean properties by type.
72 * @see #setAutowireMode
73 */
74 public static final int AUTOWIRE_BY_TYPE = AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE;
75
76 /**
77 * Constant that indicates autowiring a constructor.
78 * @see #setAutowireMode
79 */
80 public static final int AUTOWIRE_CONSTRUCTOR = AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR;
81
82 /**
83 * Constant that indicates determining an appropriate autowire strategy
84 * through introspection of the bean class.
85 * @see #setAutowireMode
86 */
87 public static final int AUTOWIRE_AUTODETECT = AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT;
88
89
90 /**
91 * Constant that indicates no dependency check at all.
92 * @see #setDependencyCheck
93 */
94 public static final int DEPENDENCY_CHECK_NONE = 0;
95
96 /**
97 * Constant that indicates dependency checking for object references.
98 * @see #setDependencyCheck
99 */
100 public static final int DEPENDENCY_CHECK_OBJECTS = 1;
101
102 /**
103 * Constant that indicates dependency checking for "simple" properties.
104 * @see #setDependencyCheck
105 * @see org.springframework.beans.BeanUtils#isSimpleProperty
106 */
107 public static final int DEPENDENCY_CHECK_SIMPLE = 2;
108
109 /**
110 * Constant that indicates dependency checking for all properties
111 * (object references as well as "simple" properties).
112 * @see #setDependencyCheck
113 */
114 public static final int DEPENDENCY_CHECK_ALL = 3;
115
116
117 private volatile Object beanClass;
118
119 private String scope = SCOPE_SINGLETON;
120
121 private boolean singleton = true;
122
123 private boolean prototype = false;
124
125 private boolean abstractFlag = false;
126
127 private boolean lazyInit = false;
128
129 private int autowireMode = AUTOWIRE_NO;
130
131 private int dependencyCheck = DEPENDENCY_CHECK_NONE;
132
133 private String[] dependsOn;
134
135 private boolean autowireCandidate = true;
136
137 private final Map qualifiers = new LinkedHashMap();
138
139 private boolean primary = false;
140
141 private ConstructorArgumentValues constructorArgumentValues;
142
143 private MutablePropertyValues propertyValues;
144
145 private MethodOverrides methodOverrides = new MethodOverrides();
146
147 private String factoryBeanName;
148
149 private String factoryMethodName;
150
151 private String initMethodName;
152
153 private String destroyMethodName;
154
155 private boolean enforceInitMethod = true;
156
157 private boolean enforceDestroyMethod = true;
158
159 private boolean synthetic = false;
160
161 private int role = BeanDefinition.ROLE_APPLICATION;
162
163 private String description;
164
165 private Resource resource;
166
167
168 /**
169 * Create a new AbstractBeanDefinition with default settings.
170 */
171 protected AbstractBeanDefinition() {
172 this(null, null);
173 }
174
175 /**
176 * Create a new AbstractBeanDefinition with the given
177 * constructor argument values and property values.
178 */
179 protected AbstractBeanDefinition(ConstructorArgumentValues cargs, MutablePropertyValues pvs) {
180 setConstructorArgumentValues(cargs);
181 setPropertyValues(pvs);
182 }
183
184 /**
185 * Create a new AbstractBeanDefinition as deep copy of the given
186 * bean definition.
187 * @param original the original bean definition to copy from
188 * @deprecated since Spring 2.5, in favor of {@link #AbstractBeanDefinition(BeanDefinition)}
189 */
190 protected AbstractBeanDefinition(AbstractBeanDefinition original) {
191 this((BeanDefinition) original);
192 }
193
194 /**
195 * Create a new AbstractBeanDefinition as deep copy of the given
196 * bean definition.
197 * @param original the original bean definition to copy from
198 */
199 protected AbstractBeanDefinition(BeanDefinition original) {
200 setParentName(original.getParentName());
201 setBeanClassName(original.getBeanClassName());
202 setFactoryBeanName(original.getFactoryBeanName());
203 setFactoryMethodName(original.getFactoryMethodName());
204 setScope(original.getScope());
205 setAbstract(original.isAbstract());
206 setLazyInit(original.isLazyInit());
207 setRole(original.getRole());
208 setConstructorArgumentValues(new ConstructorArgumentValues(original.getConstructorArgumentValues()));
209 setPropertyValues(new MutablePropertyValues(original.getPropertyValues()));
210 setSource(original.getSource());
211 copyAttributesFrom(original);
212
213 if (original instanceof AbstractBeanDefinition) {
214 AbstractBeanDefinition originalAbd = (AbstractBeanDefinition) original;
215 if (originalAbd.hasBeanClass()) {
216 setBeanClass(originalAbd.getBeanClass());
217 }
218 setAutowireMode(originalAbd.getAutowireMode());
219 setDependencyCheck(originalAbd.getDependencyCheck());
220 setDependsOn(originalAbd.getDependsOn());
221 setAutowireCandidate(originalAbd.isAutowireCandidate());
222 copyQualifiersFrom(originalAbd);
223 setPrimary(originalAbd.isPrimary());
224 setInitMethodName(originalAbd.getInitMethodName());
225 setEnforceInitMethod(originalAbd.isEnforceInitMethod());
226 setDestroyMethodName(originalAbd.getDestroyMethodName());
227 setEnforceDestroyMethod(originalAbd.isEnforceDestroyMethod());
228 setMethodOverrides(new MethodOverrides(originalAbd.getMethodOverrides()));
229 setSynthetic(originalAbd.isSynthetic());
230 setResource(originalAbd.getResource());
231 }
232 else {
233 setResourceDescription(original.getResourceDescription());
234 }
235 }
236
237
238 /**
239 * Override settings in this bean definition (assumably a copied parent
240 * from a parent-child inheritance relationship) from the given bean
241 * definition (assumably the child).
242 * @deprecated since Spring 2.5, in favor of {@link #overrideFrom(BeanDefinition)}
243 */
244 public void overrideFrom(AbstractBeanDefinition other) {
245 overrideFrom((BeanDefinition) other);
246 }
247
248 /**
249 * Override settings in this bean definition (assumably a copied parent
250 * from a parent-child inheritance relationship) from the given bean
251 * definition (assumably the child).
252 * <ul>
253 * <li>Will override beanClass if specified in the given bean definition.
254 * <li>Will always take <code>abstract</code>, <code>scope</code>,
255 * <code>lazyInit</code>, <code>autowireMode</code>, <code>dependencyCheck</code>,
256 * and <code>dependsOn</code> from the given bean definition.
257 * <li>Will add <code>constructorArgumentValues</code>, <code>propertyValues</code>,
258 * <code>methodOverrides</code> from the given bean definition to existing ones.
259 * <li>Will override <code>factoryBeanName</code>, <code>factoryMethodName</code>,
260 * <code>initMethodName</code>, and <code>destroyMethodName</code> if specified
261 * in the given bean definition.
262 * </ul>
263 */
264 public void overrideFrom(BeanDefinition other) {
265 if (other.getBeanClassName() != null) {
266 setBeanClassName(other.getBeanClassName());
267 }
268 if (other.getFactoryBeanName() != null) {
269 setFactoryBeanName(other.getFactoryBeanName());
270 }
271 if (other.getFactoryMethodName() != null) {
272 setFactoryMethodName(other.getFactoryMethodName());
273 }
274 setScope(other.getScope());
275 setAbstract(other.isAbstract());
276 setLazyInit(other.isLazyInit());
277 setRole(other.getRole());
278 getConstructorArgumentValues().addArgumentValues(other.getConstructorArgumentValues());
279 getPropertyValues().addPropertyValues(other.getPropertyValues());
280 setSource(other.getSource());
281 copyAttributesFrom(other);
282
283 if (other instanceof AbstractBeanDefinition) {
284 AbstractBeanDefinition otherAbd = (AbstractBeanDefinition) other;
285 if (otherAbd.hasBeanClass()) {
286 setBeanClass(otherAbd.getBeanClass());
287 }
288 setAutowireCandidate(otherAbd.isAutowireCandidate());
289 setAutowireMode(otherAbd.getAutowireMode());
290 copyQualifiersFrom(otherAbd);
291 setPrimary(otherAbd.isPrimary());
292 setDependencyCheck(otherAbd.getDependencyCheck());
293 setDependsOn(otherAbd.getDependsOn());
294 if (otherAbd.getInitMethodName() != null) {
295 setInitMethodName(otherAbd.getInitMethodName());
296 setEnforceInitMethod(otherAbd.isEnforceInitMethod());
297 }
298 if (otherAbd.getDestroyMethodName() != null) {
299 setDestroyMethodName(otherAbd.getDestroyMethodName());
300 setEnforceDestroyMethod(otherAbd.isEnforceDestroyMethod());
301 }
302 getMethodOverrides().addOverrides(otherAbd.getMethodOverrides());
303 setSynthetic(otherAbd.isSynthetic());
304 setResource(otherAbd.getResource());
305 }
306 else {
307 setResourceDescription(other.getResourceDescription());
308 }
309 }
310
311 /**
312 * Apply the provided default values to this bean.
313 * @param defaults the defaults to apply
314 */
315 public void applyDefaults(BeanDefinitionDefaults defaults) {
316 setLazyInit(defaults.isLazyInit());
317 setDependencyCheck(defaults.getDependencyCheck());
318 setAutowireMode(defaults.getAutowireMode());
319 setInitMethodName(defaults.getInitMethodName());
320 setEnforceInitMethod(false);
321 setDestroyMethodName(defaults.getDestroyMethodName());
322 setEnforceDestroyMethod(false);
323 }
324
325
326 /**
327 * Return whether this definition specifies a bean class.
328 */
329 public boolean hasBeanClass() {
330 return (this.beanClass instanceof Class);
331 }
332
333 /**
334 * Specify the class for this bean.
335 */
336 public void setBeanClass(Class beanClass) {
337 this.beanClass = beanClass;
338 }
339
340 /**
341 * Return the class of the wrapped bean, if already resolved.
342 * @return the bean class, or <code>null</code> if none defined
343 * @throws IllegalStateException if the bean definition does not define a bean class,
344 * or a specified bean class name has not been resolved into an actual Class
345 */
346 public Class getBeanClass() throws IllegalStateException {
347 Object beanClassObject = this.beanClass;
348 if (beanClassObject == null) {
349 throw new IllegalStateException("No bean class specified on bean definition");
350 }
351 if (!(beanClassObject instanceof Class)) {
352 throw new IllegalStateException(
353 "Bean class name [" + beanClassObject + "] has not been resolved into an actual Class");
354 }
355 return (Class) beanClassObject;
356 }
357
358 public void setBeanClassName(String beanClassName) {
359 this.beanClass = beanClassName;
360 }
361
362 public String getBeanClassName() {
363 Object beanClassObject = this.beanClass;
364 if (beanClassObject instanceof Class) {
365 return ((Class) beanClassObject).getName();
366 }
367 else {
368 return (String) beanClassObject;
369 }
370 }
371
372 /**
373 * Determine the class of the wrapped bean, resolving it from a
374 * specified class name if necessary. Will also reload a specified
375 * Class from its name when called with the bean class already resolved.
376 * @param classLoader the ClassLoader to use for resolving a (potential) class name
377 * @return the resolved bean class
378 * @throws ClassNotFoundException if the class name could be resolved
379 */
380 public Class resolveBeanClass(ClassLoader classLoader) throws ClassNotFoundException {
381 String className = getBeanClassName();
382 if (className == null) {
383 return null;
384 }
385 Class resolvedClass = ClassUtils.forName(className, classLoader);
386 this.beanClass = resolvedClass;
387 return resolvedClass;
388 }
389
390
391 /**
392 * Set the name of the target scope for the bean.
393 * <p>Default is "singleton"; the out-of-the-box alternative is "prototype".
394 * Extended bean factories might support further scopes.
395 * @see #SCOPE_SINGLETON
396 * @see #SCOPE_PROTOTYPE
397 */
398 public void setScope(String scope) {
399 Assert.notNull(scope, "Scope must not be null");
400 this.scope = scope;
401 this.singleton = SCOPE_SINGLETON.equals(scope);
402 this.prototype = SCOPE_PROTOTYPE.equals(scope);
403 }
404
405 /**
406 * Return the name of the target scope for the bean.
407 */
408 public String getScope() {
409 return this.scope;
410 }
411
412 /**
413 * Set if this a <b>Singleton</b>, with a single, shared instance returned
414 * on all calls. In case of "false", the BeanFactory will apply the <b>Prototype</b>
415 * design pattern, with each caller requesting an instance getting an independent
416 * instance. How this is exactly defined will depend on the BeanFactory.
417 * <p>"Singletons" are the commoner type, so the default is "true".
418 * Note that as of Spring 2.0, this flag is just an alternative way to
419 * specify scope="singleton" or scope="prototype".
420 * @deprecated since Spring 2.5, in favor of {@link #setScope}
421 * @see #setScope
422 * @see #SCOPE_SINGLETON
423 * @see #SCOPE_PROTOTYPE
424 */
425 public void setSingleton(boolean singleton) {
426 this.scope = (singleton ? SCOPE_SINGLETON : SCOPE_PROTOTYPE);
427 this.singleton = singleton;
428 this.prototype = !singleton;
429 }
430
431 /**
432 * Return whether this a <b>Singleton</b>, with a single shared instance
433 * returned from all calls.
434 * @see #SCOPE_SINGLETON
435 */
436 public boolean isSingleton() {
437 return this.singleton;
438 }
439
440 /**
441 * Return whether this a <b>Prototype</b>, with an independent instance
442 * returned for each call.
443 * @see #SCOPE_PROTOTYPE
444 */
445 public boolean isPrototype() {
446 return this.prototype;
447 }
448
449 /**
450 * Set if this bean is "abstract", i.e. not meant to be instantiated itself but
451 * rather just serving as parent for concrete child bean definitions.
452 * <p>Default is "false". Specify true to tell the bean factory to not try to
453 * instantiate that particular bean in any case.
454 */
455 public void setAbstract(boolean abstractFlag) {
456 this.abstractFlag = abstractFlag;
457 }
458
459 /**
460 * Return whether this bean is "abstract", i.e. not meant to be instantiated
461 * itself but rather just serving as parent for concrete child bean definitions.
462 */
463 public boolean isAbstract() {
464 return this.abstractFlag;
465 }
466
467 /**
468 * Set whether this bean should be lazily initialized.
469 * <p>If <code>false</code>, the bean will get instantiated on startup by bean
470 * factories that perform eager initialization of singletons.
471 */
472 public void setLazyInit(boolean lazyInit) {
473 this.lazyInit = lazyInit;
474 }
475
476 /**
477 * Return whether this bean should be lazily initialized, i.e. not
478 * eagerly instantiated on startup. Only applicable to a singleton bean.
479 */
480 public boolean isLazyInit() {
481 return this.lazyInit;
482 }
483
484
485 /**
486 * Set the autowire mode. This determines whether any automagical detection
487 * and setting of bean references will happen. Default is AUTOWIRE_NO,
488 * which means there's no autowire.
489 * @param autowireMode the autowire mode to set.
490 * Must be one of the constants defined in this class.
491 * @see #AUTOWIRE_NO
492 * @see #AUTOWIRE_BY_NAME
493 * @see #AUTOWIRE_BY_TYPE
494 * @see #AUTOWIRE_CONSTRUCTOR
495 * @see #AUTOWIRE_AUTODETECT
496 */
497 public void setAutowireMode(int autowireMode) {
498 this.autowireMode = autowireMode;
499 }
500
501 /**
502 * Return the autowire mode as specified in the bean definition.
503 */
504 public int getAutowireMode() {
505 return this.autowireMode;
506 }
507
508 /**
509 * Return the resolved autowire code,
510 * (resolving AUTOWIRE_AUTODETECT to AUTOWIRE_CONSTRUCTOR or AUTOWIRE_BY_TYPE).
511 * @see #AUTOWIRE_AUTODETECT
512 * @see #AUTOWIRE_CONSTRUCTOR
513 * @see #AUTOWIRE_BY_TYPE
514 */
515 public int getResolvedAutowireMode() {
516 if (this.autowireMode == AUTOWIRE_AUTODETECT) {
517 // Work out whether to apply setter autowiring or constructor autowiring.
518 // If it has a no-arg constructor it's deemed to be setter autowiring,
519 // otherwise we'll try constructor autowiring.
520 Constructor[] constructors = getBeanClass().getConstructors();
521 for (int i = 0; i < constructors.length; i++) {
522 if (constructors[i].getParameterTypes().length == 0) {
523 return AUTOWIRE_BY_TYPE;
524 }
525 }
526 return AUTOWIRE_CONSTRUCTOR;
527 }
528 else {
529 return this.autowireMode;
530 }
531 }
532
533 /**
534 * Set the dependency check code.
535 * @param dependencyCheck the code to set.
536 * Must be one of the four constants defined in this class.
537 * @see #DEPENDENCY_CHECK_NONE
538 * @see #DEPENDENCY_CHECK_OBJECTS
539 * @see #DEPENDENCY_CHECK_SIMPLE
540 * @see #DEPENDENCY_CHECK_ALL
541 */
542 public void setDependencyCheck(int dependencyCheck) {
543 this.dependencyCheck = dependencyCheck;
544 }
545
546 /**
547 * Return the dependency check code.
548 */
549 public int getDependencyCheck() {
550 return this.dependencyCheck;
551 }
552
553 /**
554 * Set the names of the beans that this bean depends on being initialized.
555 * The bean factory will guarantee that these beans get initialized before.
556 * <p>Note that dependencies are normally expressed through bean properties or
557 * constructor arguments. This property should just be necessary for other kinds
558 * of dependencies like statics (*ugh*) or database preparation on startup.
559 */
560 public void setDependsOn(String[] dependsOn) {
561 this.dependsOn = dependsOn;
562 }
563
564 /**
565 * Return the bean names that this bean depends on.
566 */
567 public String[] getDependsOn() {
568 return this.dependsOn;
569 }
570
571 /**
572 * Set whether this bean is a candidate for getting autowired into some other bean.
573 */
574 public void setAutowireCandidate(boolean autowireCandidate) {
575 this.autowireCandidate = autowireCandidate;
576 }
577
578 /**
579 * Return whether this bean is a candidate for getting autowired into some other bean.
580 */
581 public boolean isAutowireCandidate() {
582 return this.autowireCandidate;
583 }
584
585 /**
586 * Register a qualifier to be used for autowire candidate resolution,
587 * keyed by the qualifier's type name.
588 * @see AutowireCandidateQualifier#getTypeName()
589 */
590 public void addQualifier(AutowireCandidateQualifier qualifier) {
591 this.qualifiers.put(qualifier.getTypeName(), qualifier);
592 }
593
594 /**
595 * Return whether this bean has the specified qualifier.
596 */
597 public boolean hasQualifier(String typeName) {
598 return this.qualifiers.keySet().contains(typeName);
599 }
600
601 /**
602 * Return the qualifier mapped to the provided type name.
603 */
604 public AutowireCandidateQualifier getQualifier(String typeName) {
605 return (AutowireCandidateQualifier) this.qualifiers.get(typeName);
606 }
607
608 /**
609 * Return all registered qualifiers.
610 * @return the Set of {@link AutowireCandidateQualifier} objects.
611 */
612 public Set getQualifiers() {
613 return new LinkedHashSet(this.qualifiers.values());
614 }
615
616 /**
617 * Copy the qualifiers from the supplied AbstractBeanDefinition to this bean definition.
618 * @param source the AbstractBeanDefinition to copy from
619 */
620 protected void copyQualifiersFrom(AbstractBeanDefinition source) {
621 Assert.notNull(source, "Source must not be null");
622 this.qualifiers.putAll(source.qualifiers);
623 }
624
625 /**
626 * Set whether this bean is a primary autowire candidate.
627 * If this value is true for exactly one bean among multiple
628 * matching candidates, it will serve as a tie-breaker.
629 */
630 public void setPrimary(boolean primary) {
631 this.primary = primary;
632 }
633
634 /**
635 * Return whether this bean is a primary autowire candidate.
636 * If this value is true for exactly one bean among multiple
637 * matching candidates, it will serve as a tie-breaker.
638 */
639 public boolean isPrimary() {
640 return this.primary;
641 }
642
643
644 /**
645 * Specify constructor argument values for this bean.
646 */
647 public void setConstructorArgumentValues(ConstructorArgumentValues constructorArgumentValues) {
648 this.constructorArgumentValues =
649 (constructorArgumentValues != null ? constructorArgumentValues : new ConstructorArgumentValues());
650 }
651
652 /**
653 * Return constructor argument values for this bean (never <code>null</code>).
654 */
655 public ConstructorArgumentValues getConstructorArgumentValues() {
656 return this.constructorArgumentValues;
657 }
658
659 /**
660 * Return if there are constructor argument values defined for this bean.
661 */
662 public boolean hasConstructorArgumentValues() {
663 return !this.constructorArgumentValues.isEmpty();
664 }
665
666 /**
667 * Specify property values for this bean, if any.
668 */
669 public void setPropertyValues(MutablePropertyValues propertyValues) {
670 this.propertyValues = (propertyValues != null ? propertyValues : new MutablePropertyValues());
671 }
672
673 /**
674 * Return property values for this bean (never <code>null</code>).
675 */
676 public MutablePropertyValues getPropertyValues() {
677 return this.propertyValues;
678 }
679
680 /**
681 * Specify method overrides for the bean, if any.
682 */
683 public void setMethodOverrides(MethodOverrides methodOverrides) {
684 this.methodOverrides = (methodOverrides != null ? methodOverrides : new MethodOverrides());
685 }
686
687 /**
688 * Return information about methods to be overridden by the IoC
689 * container. This will be empty if there are no method overrides.
690 * Never returns null.
691 */
692 public MethodOverrides getMethodOverrides() {
693 return this.methodOverrides;
694 }
695
696
697 public void setFactoryBeanName(String factoryBeanName) {
698 this.factoryBeanName = factoryBeanName;
699 }
700
701 public String getFactoryBeanName() {
702 return this.factoryBeanName;
703 }
704
705 public void setFactoryMethodName(String factoryMethodName) {
706 this.factoryMethodName = factoryMethodName;
707 }
708
709 public String getFactoryMethodName() {
710 return this.factoryMethodName;
711 }
712
713 /**
714 * Set the name of the initializer method. The default is <code>null</code>
715 * in which case there is no initializer method.
716 */
717 public void setInitMethodName(String initMethodName) {
718 this.initMethodName = initMethodName;
719 }
720
721 /**
722 * Return the name of the initializer method.
723 */
724 public String getInitMethodName() {
725 return this.initMethodName;
726 }
727
728 /**
729 * Specify whether or not the configured init method is the default.
730 * Default value is <code>false</code>.
731 * @see #setInitMethodName
732 */
733 public void setEnforceInitMethod(boolean enforceInitMethod) {
734 this.enforceInitMethod = enforceInitMethod;
735 }
736
737 /**
738 * Indicate whether the configured init method is the default.
739 * @see #getInitMethodName()
740 */
741 public boolean isEnforceInitMethod() {
742 return this.enforceInitMethod;
743 }
744
745 /**
746 * Set the name of the destroy method. The default is <code>null</code>
747 * in which case there is no destroy method.
748 */
749 public void setDestroyMethodName(String destroyMethodName) {
750 this.destroyMethodName = destroyMethodName;
751 }
752
753 /**
754 * Return the name of the destroy method.
755 */
756 public String getDestroyMethodName() {
757 return this.destroyMethodName;
758 }
759
760 /**
761 * Specify whether or not the configured destroy method is the default.
762 * Default value is <code>false</code>.
763 * @see #setDestroyMethodName
764 */
765 public void setEnforceDestroyMethod(boolean enforceDestroyMethod) {
766 this.enforceDestroyMethod = enforceDestroyMethod;
767 }
768
769 /**
770 * Indicate whether the configured destroy method is the default.
771 * @see #getDestroyMethodName
772 */
773 public boolean isEnforceDestroyMethod() {
774 return this.enforceDestroyMethod;
775 }
776
777
778 /**
779 * Set whether this bean definition is 'synthetic', that is, not defined
780 * by the application itself (for example, an infrastructure bean such
781 * as a helper for auto-proxying, created through <code><aop:config></code>).
782 */
783 public void setSynthetic(boolean synthetic) {
784 this.synthetic = synthetic;
785 }
786
787 /**
788 * Return whether this bean definition is 'synthetic', that is,
789 * not defined by the application itself.
790 */
791 public boolean isSynthetic() {
792 return this.synthetic;
793 }
794
795 /**
796 * Set the role hint for this <code>BeanDefinition</code>.
797 */
798 public void setRole(int role) {
799 this.role = role;
800 }
801
802 /**
803 * Return the role hint for this <code>BeanDefinition</code>.
804 */
805 public int getRole() {
806 return this.role;
807 }
808
809
810 /**
811 * Set a human-readable description of this bean definition.
812 */
813 public void setDescription(String description) {
814 this.description = description;
815 }
816
817 public String getDescription() {
818 return this.description;
819 }
820
821 /**
822 * Set the resource that this bean definition came from
823 * (for the purpose of showing context in case of errors).
824 */
825 public void setResource(Resource resource) {
826 this.resource = resource;
827 }
828
829 /**
830 * Return the resource that this bean definition came from.
831 */
832 public Resource getResource() {
833 return this.resource;
834 }
835
836 /**
837 * Set a description of the resource that this bean definition
838 * came from (for the purpose of showing context in case of errors).
839 */
840 public void setResourceDescription(String resourceDescription) {
841 this.resource = new DescriptiveResource(resourceDescription);
842 }
843
844 public String getResourceDescription() {
845 return (this.resource != null ? this.resource.getDescription() : null);
846 }
847
848 /**
849 * Set the originating (e.g. decorated) BeanDefinition, if any.
850 */
851 public void setOriginatingBeanDefinition(BeanDefinition originatingBd) {
852 this.resource = new BeanDefinitionResource(originatingBd);
853 }
854
855 public BeanDefinition getOriginatingBeanDefinition() {
856 return (this.resource instanceof BeanDefinitionResource ?
857 ((BeanDefinitionResource) this.resource).getBeanDefinition() : null);
858 }
859
860 /**
861 * Validate this bean definition.
862 * @throws BeanDefinitionValidationException in case of validation failure
863 */
864 public void validate() throws BeanDefinitionValidationException {
865 if (!getMethodOverrides().isEmpty() && getFactoryMethodName() != null) {
866 throw new BeanDefinitionValidationException(
867 "Cannot combine static factory method with method overrides: " +
868 "the static factory method must create the instance");
869 }
870
871 if (hasBeanClass()) {
872 prepareMethodOverrides();
873 }
874 }
875
876 /**
877 * Validate and prepare the method overrides defined for this bean.
878 * Checks for existence of a method with the specified name.
879 * @throws BeanDefinitionValidationException in case of validation failure
880 */
881 public void prepareMethodOverrides() throws BeanDefinitionValidationException {
882 // Check that lookup methods exists.
883 MethodOverrides methodOverrides = getMethodOverrides();
884 if (!methodOverrides.isEmpty()) {
885 for (Iterator it = methodOverrides.getOverrides().iterator(); it.hasNext(); ) {
886 MethodOverride mo = (MethodOverride) it.next();
887 prepareMethodOverride(mo);
888 }
889 }
890 }
891
892 /**
893 * Validate and prepare the given method override.
894 * Checks for existence of a method with the specified name,
895 * marking it as not overloaded if none found.
896 * @param mo the MethodOverride object to validate
897 * @throws BeanDefinitionValidationException in case of validation failure
898 */
899 protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
900 int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
901 if (count == 0) {
902 throw new BeanDefinitionValidationException(
903 "Invalid method override: no method with name '" + mo.getMethodName() +
904 "' on class [" + getBeanClassName() + "]");
905 }
906 else if (count == 1) {
907 // Mark override as not overloaded, to avoid the overhead of arg type checking.
908 mo.setOverloaded(false);
909 }
910 }
911
912
913 /**
914 * Public declaration of Object's <code>clone()</code> method.
915 * Delegates to {@link #cloneBeanDefinition()}.
916 * @see java.lang.Object#clone()
917 */
918 public Object clone() {
919 return cloneBeanDefinition();
920 }
921
922 /**
923 * Clone this bean definition.
924 * To be implemented by concrete subclasses.
925 * @return the cloned bean definition object
926 */
927 public abstract AbstractBeanDefinition cloneBeanDefinition();
928
929
930 public boolean equals(Object other) {
931 if (this == other) {
932 return true;
933 }
934 if (!(other instanceof AbstractBeanDefinition)) {
935 return false;
936 }
937
938 AbstractBeanDefinition that = (AbstractBeanDefinition) other;
939
940 if (!ObjectUtils.nullSafeEquals(getBeanClassName(), that.getBeanClassName())) return false;
941 if (!ObjectUtils.nullSafeEquals(this.scope, that.scope)) return false;
942 if (this.abstractFlag != that.abstractFlag) return false;
943 if (this.lazyInit != that.lazyInit) return false;
944
945 if (this.autowireMode != that.autowireMode) return false;
946 if (this.dependencyCheck != that.dependencyCheck) return false;
947 if (!Arrays.equals(this.dependsOn, that.dependsOn)) return false;
948 if (this.autowireCandidate != that.autowireCandidate) return false;
949 if (!ObjectUtils.nullSafeEquals(this.qualifiers, that.qualifiers)) return false;
950 if (this.primary != that.primary) return false;
951
952 if (!ObjectUtils.nullSafeEquals(this.constructorArgumentValues, that.constructorArgumentValues)) return false;
953 if (!ObjectUtils.nullSafeEquals(this.propertyValues, that.propertyValues)) return false;
954 if (!ObjectUtils.nullSafeEquals(this.methodOverrides, that.methodOverrides)) return false;
955
956 if (!ObjectUtils.nullSafeEquals(this.factoryBeanName, that.factoryBeanName)) return false;
957 if (!ObjectUtils.nullSafeEquals(this.factoryMethodName, that.factoryMethodName)) return false;
958 if (!ObjectUtils.nullSafeEquals(this.initMethodName, that.initMethodName)) return false;
959 if (this.enforceInitMethod != that.enforceInitMethod) return false;
960 if (!ObjectUtils.nullSafeEquals(this.destroyMethodName, that.destroyMethodName)) return false;
961 if (this.enforceDestroyMethod != that.enforceDestroyMethod) return false;
962
963 if (this.synthetic != that.synthetic) return false;
964 if (this.role != that.role) return false;
965
966 return super.equals(other);
967 }
968
969 public int hashCode() {
970 int hashCode = ObjectUtils.nullSafeHashCode(getBeanClassName());
971 hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(this.scope);
972 hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(this.constructorArgumentValues);
973 hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(this.propertyValues);
974 hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(this.factoryBeanName);
975 hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(this.factoryMethodName);
976 hashCode = 29 * hashCode + super.hashCode();
977 return hashCode;
978 }
979
980 public String toString() {
981 StringBuffer sb = new StringBuffer("class [");
982 sb.append(getBeanClassName()).append("]");
983 sb.append("; scope=").append(this.scope);
984 sb.append("; abstract=").append(this.abstractFlag);
985 sb.append("; lazyInit=").append(this.lazyInit);
986 sb.append("; autowireMode=").append(this.autowireMode);
987 sb.append("; dependencyCheck=").append(this.dependencyCheck);
988 sb.append("; autowireCandidate=").append(this.autowireCandidate);
989 sb.append("; primary=").append(this.primary);
990 sb.append("; factoryBeanName=").append(this.factoryBeanName);
991 sb.append("; factoryMethodName=").append(this.factoryMethodName);
992 sb.append("; initMethodName=").append(this.initMethodName);
993 sb.append("; destroyMethodName=").append(this.destroyMethodName);
994 if (this.resource != null) {
995 sb.append("; defined in ").append(this.resource.getDescription());
996 }
997 return sb.toString();
998 }
999
1000 }