上一節中將瞭如何通過xml文件中讀取到bean的定義,鏈接爲 Spring 二、主要邏輯代碼賞析之獲取bean的定義 ,這一節中,我們將會講述讀取出xml文件後,如何根據bean的定義來最終生成bean。
首先還是來看一下
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
初始的時候的refresh() 方法:
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
. . .
// 此爲獲取一個 DefaultListableBeanFactory 的 beanFactory,並且會生成 XmlBeanDefinitionReader ,從xml文件中讀出beanDefinition並放置到 beanFactory中
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
. . .
// DefaultListableBeanFactory 會在此方法中根據 BeanDefinition 去加載bean的定義。
finishBeanFactoryInitialization(beanFactory);
finishRefresh();
}
catch (BeansException ex) {
. . .
// Propagate exception to caller.
throw ex;
}
finally {
. . .
}
}
}
可以看到 ,是在 finishBeanFactoryInitialization(beanFactory) 方法中將beanDefinition生成bean的。
下面我們看一下 DefultListableBeanFactory來獲取bean的方法:
@Override
public void preInstantiateSingletons() throws BeansException {
// 得到所有的bean定義的name列表
List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
// 遍歷bean定義name的列表,得到對應的bean定義
for (String beanName : beanNames) {
this.logger.debug("beanName 爲" + beanName);
// 得到bean的定義
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 如果是工廠類的bean
if (isFactoryBean(beanName)) {
final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
@Override
public Boolean run() {
return ((SmartFactoryBean<?>) factory).isEagerInit();
}
}, getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
// 如果不是工廠類的bean,即爲普通bean,則直接調用 getBean() 方法
else {
getBean(beanName);
}
}
}
}
可以看到,DefultListableBeanFactory會遍歷bean的beanName,然後調用getBean(beanName)方法來獲取到bean。getBean(beanName)即調用的 doGetBean() 方法來獲取到bean。
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
// doGetBean() ,這個方法主要做了兩件事情:
// 1、判斷是否已存在指定beanName的bean,如果有,直接返回
// 2、如果沒有,得到其beanDefinition,然後生成bean,放到map中,再返回。
// 從map中得到bean
Object sharedInstance = getSingleton(beanName);
// 如果有,那麼就肯定不用生成了,直接返回
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
// 發現如果沒有bean,那麼就得到相應的beanDefinition,然後生成bean
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
. . .
// 下面爲獲取單例bean的方法
try {
// 根據beanName來獲取到bean的beanDefinition
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
. . .
// 下面爲創建bean的方法
if (mbd.isSingleton()) {
// 這裏是實現了 ObjectFactory 這個接口,裏面得到創建的 bean
// getSingleton方法會做一些處理在同步塊中判斷是否有無bean,如果沒有,再調用回調獲取到bean,並將bean放到 singletonObjects 中,也就是最後的 beanName - > bean對象 的Map
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
logger.debug(" createBean,初始化bean所要調用的方法 ");
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
. . .
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
. . .
return (T) bean;
}
createBean(String beanName, RootBeanDefinition mbd, Object[] args)方法,其調用的是 doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) 方法,我們看一下其實現:
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
// 此爲真正去獲取一個bean的方法,也是可以大致分爲兩步:
// 1、找到其構造函數與構造函數中要傳入的value,比如constructor.newInstance()。這樣就然後生成bean的對象。相當於 User user = new User(xx,xx)
// 2、對bean對象中的value進行填充 user.setName(xxx),本質上調用的是method.invoke()方法
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 此爲創建bean,但是僅僅是創建bean,裏面的value不填充。因爲要創建,所以 如果construction中有依賴,那麼肯定要先加載 construction 中的依賴,
// 如果依賴是bean,那麼就加載要依賴的bean
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 此爲得到創建好的bean
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<Object>() {
@Override
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
try {
// bean創建完成後,調用下面的方法根據beanDefinition中定義的value對bean進行填充
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
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);
}
}
. . .
// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
好,我們首先看一下 createBeanInstance() ,即創建bean的方法:
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
. . .
// 此爲判斷bean的構造方法中是否需要value的注入,如果有,那麼走 autowireConstructor 方法,先找到value
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
// 如果沒有,直接走 instantiateBean ,直接生成一個bean
return instantiateBean(beanName, mbd);
}
那麼比如是
<bean id="dependC" class="com.happyheng.bean.DependC">
<constructor-arg ref="dependA"/>
</bean>
那麼肯定需要走 autowireConstructor() ,因爲構造方法裏面有value需要創建。在 autowireConstructor() 中,首先去獲取裏面的value值
private int resolveConstructorArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw,
ConstructorArgumentValues cargs, ConstructorArgumentValues resolvedValues) {
. . .
for (ConstructorArgumentValues.ValueHolder valueHolder : cargs.getGenericArgumentValues()) {
// 遍歷 Constructor 參數
if (valueHolder.isConverted()) {
resolvedValues.addGenericArgumentValue(valueHolder);
}
else {
// 得到 Constructor 參數裏面的value
Object resolvedValue =
valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue());
// 得到value之後,替換ConstructorArgumentValues.ValueHolder中的value
ConstructorArgumentValues.ValueHolder resolvedValueHolder =
new ConstructorArgumentValues.ValueHolder(resolvedValue, valueHolder.getType(), valueHolder.getName());
resolvedValueHolder.setSource(valueHolder);
resolvedValues.addGenericArgumentValue(resolvedValueHolder);
}
}
return minNrOfArgs;
}
在獲取value值的時候,有這樣的方法:
public Object resolveValueIfNecessary(Object argName, Object value) {
// 如果value是 RuntimeBeanReference ,那麼需要先獲取到這個bean,即如果有,就直接拿到返回,如果沒有,就創建
if (value instanceof RuntimeBeanReference) {
RuntimeBeanReference ref = (RuntimeBeanReference) value;
return resolveReference(argName, ref);
}
. . .
}
所以如果 dependC 的構造函數中有 dependA 的話,那麼需要先生成dependA這個bean,最後再生成 dependC 這個bean 。
dependC在獲取到了所有構造函數的值後(即dependA已經生成),會在autowireConstructor() 方法的最後 調用 instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner, final Constructor<?> ctor, Object... args) 方法來傳入Constructor與對應的args利用反射來生成bean。
至於前面所說的構造函數中沒有參數的bean,比如:
<bean id="myBean" class="com.happyheng.bean.MyBean"/>
則直接調用 instantiateBean(beanName, mbd) 方法,其調用了方法:
@Override
public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {
/**
* @todo
*/
// 使用了java的反射,先得到bean的Class的 constructor 的方法,然後直接使用 constructor 方法來生成一個bean
if (bd.getMethodOverrides().isEmpty()) {
Constructor<?> constructorToUse;
synchronized (bd.constructorArgumentLock) {
constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
if (constructorToUse == null) {
// 得到bean的Class對象
final Class<?> clazz = bd.getBeanClass();
if (clazz.isInterface()) {
throw new BeanInstantiationException(clazz, "Specified class is an interface");
}
try {
if (System.getSecurityManager() != null) {
constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor<?>>() {
@Override
public Constructor<?> run() throws Exception {
return clazz.getDeclaredConstructor((Class[]) null);
}
});
}
else {
// 得到這個bean的 Constructor 方法
constructorToUse = clazz.getDeclaredConstructor((Class[]) null);
}
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Exception ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
// 將 Constructor 方法傳入到 BeanUtils 來直接生成一個對象即可
return BeanUtils.instantiateClass(constructorToUse);
}
else {
// Must generate CGLIB subclass.
return instantiateWithMethodInjection(bd, beanName, owner);
}
}