Abstract bean factory superclass that implements default bean creation,
with the full capabilities specified by the
Provides bean creation (with constructor resolution), property population,
wiring (including autowiring), and initialization. Handles runtime bean
references, resolves managed collections, calls initialization methods, etc.
Supports autowiring constructors, properties by name, and properties by type.
| Method from org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory Detail: |
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean,
String beanName) throws BeansException {
Object result = existingBean;
for (Iterator it = getBeanPostProcessors().iterator(); it.hasNext();) {
BeanPostProcessor beanProcessor = (BeanPostProcessor) it.next();
result = beanProcessor.postProcessAfterInitialization(result, beanName);
}
return result;
}
|
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean,
String beanName) throws BeansException {
Object result = existingBean;
for (Iterator it = getBeanPostProcessors().iterator(); it.hasNext();) {
BeanPostProcessor beanProcessor = (BeanPostProcessor) it.next();
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
}
return result;
}
|
protected Object applyBeanPostProcessorsBeforeInstantiation(Class beanClass,
String beanName) throws BeansException {
for (Iterator it = getBeanPostProcessors().iterator(); it.hasNext();) {
BeanPostProcessor beanProcessor = (BeanPostProcessor) it.next();
if (beanProcessor instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) beanProcessor;
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
return null;
}
Apply InstantiationAwareBeanPostProcessors to the specified bean definition
(by class and name), invoking their postProcessBeforeInstantiation methods.
Any returned object will be used as the bean instead of actually instantiating
the target bean. A null return value from the post-processor will
result in the target bean being instantiated. |
public void applyBeanPropertyValues(Object existingBean,
String beanName) throws BeansException {
markBeanAsCreated(beanName);
BeanDefinition bd = getMergedBeanDefinition(beanName);
BeanWrapper bw = new BeanWrapperImpl(existingBean);
initBeanWrapper(bw);
applyPropertyValues(beanName, bd, bw, bd.getPropertyValues());
}
|
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd,
Class beanType,
String beanName) throws BeansException {
for (Iterator it = getBeanPostProcessors().iterator(); it.hasNext();) {
BeanPostProcessor beanProcessor = (BeanPostProcessor) it.next();
if (beanProcessor instanceof MergedBeanDefinitionPostProcessor) {
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) beanProcessor;
bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
}
}
Apply MergedBeanDefinitionPostProcessors to the specified bean definition,
invoking their postProcessMergedBeanDefinition methods. |
protected void applyPropertyValues(String beanName,
BeanDefinition mbd,
BeanWrapper bw,
PropertyValues pvs) {
if (pvs == null || pvs.isEmpty()) {
return;
}
MutablePropertyValues mpvs = null;
List original = null;
if (pvs instanceof MutablePropertyValues) {
mpvs = (MutablePropertyValues) pvs;
if (mpvs.isConverted()) {
// Shortcut: use the pre-converted values as-is.
try {
bw.setPropertyValues(mpvs);
return;
}
catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
original = mpvs.getPropertyValueList();
}
else {
original = Arrays.asList(pvs.getPropertyValues());
}
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);
// Create a deep copy, resolving any references for values.
List deepCopy = new ArrayList(original.size());
boolean resolveNecessary = false;
for (Iterator it = original.iterator(); it.hasNext();) {
PropertyValue pv = (PropertyValue) it.next();
if (pv.isConverted()) {
deepCopy.add(pv);
}
else {
String propertyName = pv.getName();
Object originalValue = pv.getValue();
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
Object convertedValue = resolvedValue;
boolean convertible = !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
if (convertible) {
convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
}
// Possibly store converted value in merged bean definition,
// in order to avoid re-conversion for every created bean instance.
if (resolvedValue == originalValue) {
if (convertible) {
pv.setConvertedValue(convertedValue);
}
deepCopy.add(pv);
}
else if (originalValue instanceof TypedStringValue && convertible) {
pv.setConvertedValue(convertedValue);
deepCopy.add(pv);
}
else {
resolveNecessary = true;
deepCopy.add(new PropertyValue(pv, convertedValue));
}
}
}
if (mpvs != null && !resolveNecessary) {
mpvs.setConverted();
}
// Set our (possibly massaged) deep copy.
try {
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}
catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
Apply the given property values, resolving any runtime references
to other beans in this bean factory. Must use deep copy, so we
don't permanently modify this property. |
public Object autowire(Class beanClass,
int autowireMode,
boolean dependencyCheck) throws BeansException {
// Use non-singleton bean definition, to avoid registering bean as dependent bean.
RootBeanDefinition bd = new RootBeanDefinition(beanClass, autowireMode, dependencyCheck);
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
if (bd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR) {
return autowireConstructor(beanClass.getName(), bd, null, null).getWrappedInstance();
}
else {
Object bean = getInstantiationStrategy().instantiate(bd, null, this);
populateBean(beanClass.getName(), bd, new BeanWrapperImpl(bean));
return bean;
}
}
|
public void autowireBean(Object existingBean) {
// Use non-singleton bean definition, to avoid registering bean as dependent bean.
RootBeanDefinition bd = new RootBeanDefinition(ClassUtils.getUserClass(existingBean));
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
BeanWrapper bw = new BeanWrapperImpl(existingBean);
initBeanWrapper(bw);
populateBean(bd.getBeanClass().getName(), bd, bw);
}
|
public void autowireBeanProperties(Object existingBean,
int autowireMode,
boolean dependencyCheck) throws BeansException {
if (autowireMode == AUTOWIRE_CONSTRUCTOR) {
throw new IllegalArgumentException("AUTOWIRE_CONSTRUCTOR not supported for existing bean instance");
}
// Use non-singleton bean definition, to avoid registering bean as dependent bean.
RootBeanDefinition bd =
new RootBeanDefinition(ClassUtils.getUserClass(existingBean), autowireMode, dependencyCheck);
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
BeanWrapper bw = new BeanWrapperImpl(existingBean);
initBeanWrapper(bw);
populateBean(bd.getBeanClass().getName(), bd, bw);
}
|
protected void autowireByName(String beanName,
AbstractBeanDefinition mbd,
BeanWrapper bw,
MutablePropertyValues pvs) {
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (int i = 0; i < propertyNames.length; i++) {
String propertyName = propertyNames[i];
if (containsBean(propertyName)) {
Object bean = getBean(propertyName);
pvs.addPropertyValue(propertyName, bean);
registerDependentBean(propertyName, beanName);
if (logger.isDebugEnabled()) {
logger.debug("Added autowiring by name from bean name '" + beanName +
"' via property '" + propertyName + "' to bean named '" + propertyName + "'");
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
"' by name: no matching bean found");
}
}
}
}
Fill in any missing property values with references to
other beans in this factory if autowire is set to "byName". |
protected void autowireByType(String beanName,
AbstractBeanDefinition mbd,
BeanWrapper bw,
MutablePropertyValues pvs) {
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
Set autowiredBeanNames = new LinkedHashSet(4);
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (int i = 0; i < propertyNames.length; i++) {
String propertyName = propertyNames[i];
try {
PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
// Do not allow eager init for type matching in case of a prioritized post-processor.
boolean eager = !PriorityOrdered.class.isAssignableFrom(bw.getWrappedClass());
DependencyDescriptor desc = new DependencyDescriptor(methodParam, false, eager);
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
if (autowiredArgument != null) {
pvs.addPropertyValue(propertyName, autowiredArgument);
}
for (Iterator it = autowiredBeanNames.iterator(); it.hasNext();) {
String autowiredBeanName = (String) it.next();
registerDependentBean(autowiredBeanName, beanName);
if (logger.isDebugEnabled()) {
logger.debug("Autowiring by type from bean name '" + beanName + "' via property '" +
propertyName + "' to bean named '" + autowiredBeanName + "'");
}
}
autowiredBeanNames.clear();
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
}
}
}
Abstract method defining "autowire by type" (bean properties by type) behavior.
This is like PicoContainer default, in which there must be exactly one bean
of the property type in the bean factory. This makes bean factories simple to
configure for small namespaces, but doesn't work as well as standard Spring
behavior for bigger applications. |
protected BeanWrapper autowireConstructor(String beanName,
RootBeanDefinition mbd,
Constructor[] ctors,
Object[] explicitArgs) {
ConstructorResolver constructorResolver =
new ConstructorResolver(this, this, getInstantiationStrategy(), getCustomTypeConverter());
return constructorResolver.autowireConstructor(beanName, mbd, ctors, explicitArgs);
}
"autowire constructor" (with constructor arguments by type) behavior.
Also applied if explicit constructor argument values are specified,
matching all remaining arguments with beans from the bean factory.
This corresponds to constructor injection: In this mode, a Spring
bean factory is able to host components that expect constructor-based
dependency resolution. |
protected void checkDependencies(String beanName,
AbstractBeanDefinition mbd,
PropertyDescriptor[] pds,
PropertyValues pvs) throws UnsatisfiedDependencyException {
int dependencyCheck = mbd.getDependencyCheck();
for (int i = 0; i < pds.length; i++) {
if (pds[i].getWriteMethod() != null && !pvs.contains(pds[i].getName())) {
boolean isSimple = BeanUtils.isSimpleProperty(pds[i].getPropertyType());
boolean unsatisfied = (dependencyCheck == RootBeanDefinition.DEPENDENCY_CHECK_ALL) ||
(isSimple && dependencyCheck == RootBeanDefinition.DEPENDENCY_CHECK_SIMPLE) ||
(!isSimple && dependencyCheck == RootBeanDefinition.DEPENDENCY_CHECK_OBJECTS);
if (unsatisfied) {
throw new UnsatisfiedDependencyException(
mbd.getResourceDescription(), beanName, pds[i].getName(),
"Set this property value or disable dependency checking for this bean.");
}
}
}
}
Perform a dependency check that all properties exposed have been set,
if desired. Dependency checks can be objects (collaborating beans),
simple (primitives and String), or all (both). |
public Object configureBean(Object existingBean,
String beanName) throws BeansException {
markBeanAsCreated(beanName);
BeanDefinition mbd = getMergedBeanDefinition(beanName);
RootBeanDefinition bd = null;
if (mbd instanceof RootBeanDefinition) {
RootBeanDefinition rbd = (RootBeanDefinition) mbd;
if (SCOPE_PROTOTYPE.equals(rbd.getScope())) {
bd = rbd;
}
}
if (bd == null) {
bd = new RootBeanDefinition(mbd);
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
}
BeanWrapper bw = new BeanWrapperImpl(existingBean);
initBeanWrapper(bw);
populateBean(beanName, bd, bw);
return initializeBean(beanName, existingBean, bd);
}
|
public void copyConfigurationFrom(ConfigurableBeanFactory otherFactory) {
super.copyConfigurationFrom(otherFactory);
if (otherFactory instanceof AbstractAutowireCapableBeanFactory) {
AbstractAutowireCapableBeanFactory otherAutowireFactory =
(AbstractAutowireCapableBeanFactory) otherFactory;
this.instantiationStrategy = otherAutowireFactory.instantiationStrategy;
this.allowCircularReferences = otherAutowireFactory.allowCircularReferences;
this.ignoredDependencyTypes.addAll(otherAutowireFactory.ignoredDependencyTypes);
this.ignoredDependencyInterfaces.addAll(otherAutowireFactory.ignoredDependencyInterfaces);
}
}
|
public Object createBean(Class beanClass) throws BeansException {
// Use prototype bean definition, to avoid registering bean as dependent bean.
RootBeanDefinition bd = new RootBeanDefinition(beanClass);
bd.setScope(SCOPE_PROTOTYPE);
return createBean(beanClass.getName(), bd, null);
}
|
public Object createBean(Class beanClass,
int autowireMode,
boolean dependencyCheck) throws BeansException {
// Use non-singleton bean definition, to avoid registering bean as dependent bean.
RootBeanDefinition bd = new RootBeanDefinition(beanClass, autowireMode, dependencyCheck);
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
return createBean(beanClass.getName(), bd, null);
}
|
protected Object createBean(String beanName,
RootBeanDefinition mbd,
Object[] args) throws BeanCreationException {
AccessControlContext acc = AccessController.getContext();
return AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
// Make sure bean class is actually resolved at this point.
resolveBeanClass(mbd, beanName);
// Prepare method overrides.
try {
mbd.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbd.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbd);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
Object beanInstance = doCreateBean(beanName, mbd, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
}, acc);
}
Central method of this class: creates a bean instance,
populates the bean instance, applies post-processors, etc. |
protected BeanWrapper createBeanInstance(String beanName,
RootBeanDefinition mbd,
Object[] args) {
// Make sure bean class is actually resolved at this point.
Class beanClass = resolveBeanClass(mbd, beanName);
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// Shortcut when re-creating the same bean...
if (mbd.resolvedConstructorOrFactoryMethod != null) {
if (mbd.constructorArgumentsResolved) {
return autowireConstructor(beanName, mbd, null, args);
}
else {
return instantiateBean(beanName, mbd);
}
}
// Need to determine the constructor...
Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
// No special handling: simply use no-arg constructor.
return instantiateBean(beanName, mbd);
}
Create a new instance for the specified bean, using an appropriate instantiation strategy:
factory method, constructor autowiring, or simple instantiation. |
protected Constructor[] determineConstructorsFromBeanPostProcessors(Class beanClass,
String beanName) throws BeansException {
if (hasInstantiationAwareBeanPostProcessors()) {
for (Iterator it = getBeanPostProcessors().iterator(); it.hasNext();) {
BeanPostProcessor beanProcessor = (BeanPostProcessor) it.next();
if (beanProcessor instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) beanProcessor;
Constructor[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
if (ctors != null) {
return ctors;
}
}
}
}
return null;
}
|
protected Object doCreateBean(String beanName,
RootBeanDefinition mbd,
Object[] args) {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = (BeanWrapper) this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, new ObjectFactory() {
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set actualDependentBeans = new LinkedHashSet(dependentBeans.length);
for (int i = 0; i < dependentBeans.length; i++) {
String dependentBean = dependentBeans[i];
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
registerDisposableBeanIfNecessary(beanName, bean, mbd);
return exposedObject;
}
Actually create the specified bean. Pre-creation processing has already happened
at this point, e.g. checking postProcessBeforeInstantiation callbacks.
Differentiates between default bean instantiation, use of a
factory method, and autowiring a constructor. |
protected PropertyDescriptor[] filterPropertyDescriptorsForDependencyCheck(BeanWrapper bw) {
synchronized (this.filteredPropertyDescriptorsCache) {
PropertyDescriptor[] filtered = (PropertyDescriptor[])
this.filteredPropertyDescriptorsCache.get(bw.getWrappedClass());
if (filtered == null) {
List pds = new LinkedList(Arrays.asList(bw.getPropertyDescriptors()));
for (Iterator it = pds.iterator(); it.hasNext();) {
PropertyDescriptor pd = (PropertyDescriptor) it.next();
if (isExcludedFromDependencyCheck(pd)) {
it.remove();
}
}
filtered = (PropertyDescriptor[]) pds.toArray(new PropertyDescriptor[pds.size()]);
this.filteredPropertyDescriptorsCache.put(bw.getWrappedClass(), filtered);
}
return filtered;
}
}
Extract a filtered set of PropertyDescriptors from the given BeanWrapper,
excluding ignored dependency types or properties defined on ignored
dependency interfaces. |
protected Object getEarlyBeanReference(String beanName,
RootBeanDefinition mbd,
Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (Iterator it = getBeanPostProcessors().iterator(); it.hasNext(); ) {
BeanPostProcessor bp = (BeanPostProcessor) it.next();
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}
Obtain a reference for early access to the specified bean,
typically for the purpose of resolving a circular reference. |
protected InstantiationStrategy getInstantiationStrategy() {
return this.instantiationStrategy;
}
Return the instantiation strategy to use for creating bean instances. |
protected Class getTypeForFactoryBean(String beanName,
RootBeanDefinition mbd) {
FactoryBean fb = (mbd.isSingleton() ?
getSingletonFactoryBeanForTypeCheck(beanName, mbd) :
getNonSingletonFactoryBeanForTypeCheck(beanName, mbd));
if (fb != null) {
// Try to obtain the FactoryBean's object type from this early stage of the instance.
Class objectType = getTypeForFactoryBean(fb);
if (objectType != null) {
return objectType;
}
}
// No type found - fall back to full creation of the FactoryBean instance.
return super.getTypeForFactoryBean(beanName, mbd);
}
This implementation checks the FactoryBean's getObjectType method
on a plain instance of the FactoryBean, without bean properties applied yet.
If this doesn't return a type yet, a full creation of the FactoryBean is
used as fallback (through delegation to the superclass's implementation).
The shortcut check for a FactoryBean is only applied in case of a singleton
FactoryBean. If the FactoryBean instance itself is not kept as singleton,
it will be fully created to check the type of its exposed object. |
protected Class getTypeForFactoryMethod(String beanName,
RootBeanDefinition mbd,
Class[] typesToMatch) {
Class factoryClass = null;
boolean isStatic = true;
String factoryBeanName = mbd.getFactoryBeanName();
if (factoryBeanName != null) {
if (factoryBeanName.equals(beanName)) {
throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
"factory-bean reference points back to the same bean definition");
}
// Check declared factory method return type on factory class.
factoryClass = getType(factoryBeanName);
isStatic = false;
}
else {
// Check declared factory method return type on bean class.
factoryClass = resolveBeanClass(mbd, beanName, typesToMatch);
}
if (factoryClass == null) {
return null;
}
// If all factory methods have the same return type, return that type.
// Can't clearly figure out exact method due to type converting / autowiring!
int minNrOfArgs = mbd.getConstructorArgumentValues().getArgumentCount();
Method[] candidates = ReflectionUtils.getAllDeclaredMethods(factoryClass);
Set returnTypes = new HashSet(1);
for (int i = 0; i < candidates.length; i++) {
Method factoryMethod = candidates[i];
if (Modifier.isStatic(factoryMethod.getModifiers()) == isStatic &&
factoryMethod.getName().equals(mbd.getFactoryMethodName()) &&
factoryMethod.getParameterTypes().length >= minNrOfArgs) {
returnTypes.add(factoryMethod.getReturnType());
}
}
if (returnTypes.size() == 1) {
// Clear return type found: all factory methods return same type.
return (Class) returnTypes.iterator().next();
}
else {
// Ambiguous return types found: return null to indicate "not determinable".
return null;
}
}
Determine the bean type for the given bean definition which is based on
a factory method. Only called if there is no singleton instance registered
for the target bean already.
This implementation determines the type matching #createBean 's
different creation strategies. As far as possible, we'll perform static
type checking to avoid creation of the target bean. |
public void ignoreDependencyInterface(Class ifc) {
this.ignoredDependencyInterfaces.add(ifc);
}
Ignore the given dependency interface for autowiring.
This will typically be used by application contexts to register
dependencies that are resolved in other ways, like BeanFactory through
BeanFactoryAware or ApplicationContext through ApplicationContextAware.
By default, only the BeanFactoryAware interface is ignored.
For further types to ignore, invoke this method for each type. |
public void ignoreDependencyType(Class type) {
this.ignoredDependencyTypes.add(type);
}
Ignore the given dependency type for autowiring:
for example, String. Default is none. |
public Object initializeBean(Object existingBean,
String beanName) {
return initializeBean(beanName, existingBean, null);
}
|
protected Object initializeBean(String beanName,
Object bean,
RootBeanDefinition mbd) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(this);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
Initialize the given bean instance, applying factory callbacks
as well as init methods and bean post processors.
Called from #createBean for traditionally defined beans,
and from #initializeBean for existing bean instances. |
protected BeanWrapper instantiateBean(String beanName,
RootBeanDefinition mbd) {
try {
Object beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
initBeanWrapper(bw);
return bw;
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
}
}
Instantiate the given bean using its default constructor. |
protected BeanWrapper instantiateUsingFactoryMethod(String beanName,
RootBeanDefinition mbd,
Object[] explicitArgs) {
ConstructorResolver constructorResolver =
new ConstructorResolver(this, this, getInstantiationStrategy(), getCustomTypeConverter());
return constructorResolver.instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);
}
Instantiate the bean using a named factory method. The method may be static, if the
mbd parameter specifies a class, rather than a factoryBean, or an instance variable
on a factory object itself configured using Dependency Injection. |
protected void invokeCustomInitMethod(String beanName,
Object bean,
String initMethodName,
boolean enforceInitMethod) throws Throwable {
Method initMethod = BeanUtils.findMethod(bean.getClass(), initMethodName, null);
if (initMethod == null) {
if (enforceInitMethod) {
throw new NoSuchMethodException("Couldn't find an init method named '" + initMethodName +
"' on bean with name '" + beanName + "'");
}
else {
if (logger.isDebugEnabled()) {
logger.debug("No default init method named '" + initMethodName +
"' found on bean with name '" + beanName + "'");
}
// Ignore non-existent default lifecycle methods.
return;
}
}
if (logger.isDebugEnabled()) {
logger.debug("Invoking init method '" + initMethodName + "' on bean with name '" + beanName + "'");
}
ReflectionUtils.makeAccessible(initMethod);
try {
initMethod.invoke(bean, (Object[]) null);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
|
protected void invokeInitMethods(String beanName,
Object bean,
RootBeanDefinition mbd) throws Throwable {
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isDebugEnabled()) {
logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
((InitializingBean) bean).afterPropertiesSet();
}
String initMethodName = (mbd != null ? mbd.getInitMethodName() : null);
if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, initMethodName, mbd.isEnforceInitMethod());
}
}
Give a bean a chance to react now all its properties are set,
and a chance to know about its owning bean factory (this object).
This means checking whether the bean implements InitializingBean or defines
a custom init method, and invoking the necessary callback(s) if it does. |
protected boolean isExcludedFromDependencyCheck(PropertyDescriptor pd) {
return (AutowireUtils.isExcludedFromDependencyCheck(pd) ||
this.ignoredDependencyTypes.contains(pd.getPropertyType()) ||
AutowireUtils.isSetterDefinedInInterface(pd, this.ignoredDependencyInterfaces));
}
Determine whether the given bean property is excluded from dependency checks.
This implementation excludes properties defined by CGLIB and
properties whose type matches an ignored dependency type or which
are defined by an ignored dependency interface. |
protected void populateBean(String beanName,
AbstractBeanDefinition mbd,
BeanWrapper bw) {
PropertyValues pvs = mbd.getPropertyValues();
if (bw == null) {
if (!pvs.isEmpty()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// Skip property population phase for null instance.
return;
}
}
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (Iterator it = getBeanPostProcessors().iterator(); it.hasNext();) {
BeanPostProcessor beanProcessor = (BeanPostProcessor) it.next();
if (beanProcessor instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) beanProcessor;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
if (!continueWithPropertyPopulation) {
return;
}
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw);
if (hasInstAwareBpps) {
for (Iterator it = getBeanPostProcessors().iterator(); it.hasNext(); ) {
BeanPostProcessor beanProcessor = (BeanPostProcessor) it.next();
if (beanProcessor instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) beanProcessor;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
if (needsDepCheck) {
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
applyPropertyValues(beanName, mbd, bw, pvs);
}
Populate the bean instance in the given BeanWrapper with the property values
from the bean definition. |
protected Object postProcessObjectFromFactoryBean(Object object,
String beanName) {
return applyBeanPostProcessorsAfterInitialization(object, beanName);
}
Applies the postProcessAfterInitialization callback of all
registered BeanPostProcessors, giving them a chance to post-process the
object obtained from FactoryBeans (for example, to auto-proxy them). |
protected Class predictBeanType(String beanName,
RootBeanDefinition mbd,
Class[] typesToMatch) {
Class beanClass = null;
if (mbd.getFactoryMethodName() != null) {
beanClass = getTypeForFactoryMethod(beanName, mbd, typesToMatch);
}
else {
beanClass = resolveBeanClass(mbd, beanName, typesToMatch);
}
// Apply SmartInstantiationAwareBeanPostProcessors to predict the
// eventual type after a before-instantiation shortcut.
if (beanClass != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (Iterator it = getBeanPostProcessors().iterator(); it.hasNext(); ) {
BeanPostProcessor bp = (BeanPostProcessor) it.next();
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
Class processedType = ibp.predictBeanType(beanClass, beanName);
if (processedType != null) {
return processedType;
}
}
}
}
return beanClass;
}
|
protected void removeSingleton(String beanName) {
super.removeSingleton(beanName);
this.factoryBeanInstanceCache.remove(beanName);
}
Overridden to clear FactoryBean instance cache as well. |
protected Object resolveBeforeInstantiation(String beanName,
RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
if (mbd.hasBeanClass() && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
bean = applyBeanPostProcessorsBeforeInstantiation(mbd.getBeanClass(), beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
mbd.beforeInstantiationResolved = Boolean.valueOf(bean != null);
}
return bean;
}
Apply before-instantiation post-processors, resolving whether there is a
before-instantiation shortcut for the specified bean. |
public Object resolveDependency(DependencyDescriptor descriptor,
String beanName) throws BeansException {
return resolveDependency(descriptor, beanName, null, null);
}
|
public void setAllowCircularReferences(boolean allowCircularReferences) {
this.allowCircularReferences = allowCircularReferences;
}
Set whether to allow circular references between beans - and automatically
try to resolve them.
Note that circular reference resolution means that one of the involved beans
will receive a reference to another bean that is not fully initialized yet.
This can lead to subtle and not-so-subtle side effects on initialization;
it does work fine for many scenarios, though.
Default is "true". Turn this off to throw an exception when encountering
a circular reference, disallowing them completely.
NOTE: It is generally recommended to not rely on circular references
between your beans. Refactor your application logic to have the two beans
involved delegate to a third bean that encapsulates their common logic. |
public void setAllowRawInjectionDespiteWrapping(boolean allowRawInjectionDespiteWrapping) {
this.allowRawInjectionDespiteWrapping = allowRawInjectionDespiteWrapping;
}
Set whether to allow the raw injection of a bean instance into some other
bean's property, despite the injected bean eventually getting wrapped
(for example, through AOP auto-proxying).
This will only be used as a last resort in case of a circular reference
that cannot be resolved otherwise: essentially, preferring a raw instance
getting injected over a failure of the entire bean wiring process.
Default is "false", as of Spring 2.0. Turn this on to allow for non-wrapped
raw beans injected into some of your references, which was Spring 1.2's
(arguably unclean) default behavior.
NOTE: It is generally recommended to not rely on circular references
between your beans, in particular with auto-proxying involved. |
public void setInstantiationStrategy(InstantiationStrategy instantiationStrategy) {
this.instantiationStrategy = instantiationStrategy;
}
Set the instantiation strategy to use for creating bean instances.
Default is CglibSubclassingInstantiationStrategy. |
protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd,
BeanWrapper bw) {
Set result = new TreeSet();
PropertyValues pvs = mbd.getPropertyValues();
PropertyDescriptor[] pds = bw.getPropertyDescriptors();
for (int i = 0; i < pds.length; i++) {
if (pds[i].getWriteMethod() != null && !isExcludedFromDependencyCheck(pds[i]) &&
!pvs.contains(pds[i].getName()) && !BeanUtils.isSimpleProperty(pds[i].getPropertyType())) {
result.add(pds[i].getName());
}
}
return StringUtils.toStringArray(result);
}
Return an array of non-simple bean properties that are unsatisfied.
These are probably unsatisfied references to other beans in the
factory. Does not include simple properties like primitives or Strings. |