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