上一節說完BeanDefinition中的beanClass屬性從String轉換成了Class。這一節繼續看看beanDefinition發生了什麼,
回到上一節的方法createBean:
/**
* Central method of this class: creates a bean instance,
* populates the bean instance, applies post-processors, etc.
* @see #doCreateBean
*/
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
try {
mbdToUse.prepareMethodOverrides();
}
try {
// 曾經有一份真摯的愛情擺在我面前,我沒有珍惜。。。Give BeanPostProcessors a
//chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
try {
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
}
}
resolveBeanClass之後,有一段代碼是給編程人員一個機會,打斷正常的bean的實例化過程,自定義實例化操作。所以名字叫bean創建的過程的仙履奇緣,需要實現InstantiaitionAwareBeanPostProcess接口,
仔細觀察一下InstantiationAwareBeanPostProcessor
InstantiationAwareBeanPostProcessor 繼承了 BeanPostProcessor 接口,接口說明上簡單的介紹了一下,這個接口是一個回調接口,定義了在bean的實例化之前和之後被調用的兩個方法,而且是在注入bean的屬性之前。
所以這一點很重要,postProcessBeforeInitialization是在注入配置屬性(properties inject)之前做用到的。看簡單的示例
public class BeanInstranitionAwareImpl implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
// Assert.isNull(beanClass,"beanClass不能爲空");
if(ObjectUtils.nullSafeEquals(beanClass, SuperUser.class)){
SuperUser superUser = new SuperUser();
superUser.setName("一個船新的版本");
superUser.setAge(22);
return superUser;
}
return null;
}
}
可以上面的實現,在beanClass是SuperUser的類型時,直接返回一個全新的對象。如果不想特殊處理bean,可以默認返回null,表示該bean還是默認使用spring的實例化方法。
下面是仙履奇緣中至尊寶的英文版本:
* Subinterface of {@link BeanPostProcessor} that adds a before-instantiation callback,
* and a callback after instantiation but before explicit properties are set or
* autowiring occurs.
*
* <p>Typically used to suppress default instantiation for specific target beans,
* for example to create proxies with special TargetSources (pooling targets,
* lazily initializing targets, etc), or to implement additional injection strategies
* such as field injection.