白話Spring原始碼(五):Bean的建立過程
我們知道可以通過name從beanFactory獲取對應bean物件,那bean是怎麼建立的呢?
我們先設想如果我們來建立物件需要哪幾步呢?
1.找到物件的class
2.通過反射建立物件
3.設定物件的屬性值
其實spring建立物件的也是主要分這幾步,下面我們進入原始碼看看吧!
上篇部落格我們瞭解了beanFactory的結構,但那都是介面並沒有具體實現,beanFactory的getBean(String name)是獲取bean例項的方法,他的第一個實現是在AbstractBeanFactory的抽象類裡
AbstractBeanFactory的getBean:
public Object getBean(String name) throws BeansException { String beanName = transformedBeanName(name);//轉換name,主要是對FactoryBean進行處理,下面部落格會講解FactoryBean Object sharedInstance = this.singletonCache.get(beanName);//看看單例裡有沒有bean例項,因為單例是先建立好,放到map裡的 if (sharedInstance != null) { if (logger.isDebugEnabled()) { logger.debug("Returning cached instance of singleton bean '" + beanName + "'"); } return getObjectForSharedInstance(name, sharedInstance);//如果單列裡有對直接從map中get出來 } else {//如果單例的map裡沒有就建立 RootBeanDefinition mergedBeanDefinition = null; try { mergedBeanDefinition = getMergedBeanDefinition(beanName, false);//獲取bean對應的class資訊,class資訊封裝在RootBeanDefinition } catch (NoSuchBeanDefinitionException ex) { if (this.parentBeanFactory != null) { return this.parentBeanFactory.getBean(name);//如果當前工廠沒找到class,就從父級的工廠裡找 } throw ex; } // create bean instance if (mergedBeanDefinition.isSingleton()) {//判斷是不是配置成單例,如果是單列,建立好,放到單例的map裡 synchronized (this.singletonCache) { // re-check singleton cache within synchronized block sharedInstance = this.singletonCache.get(beanName); if (sharedInstance == null) { logger.info("Creating shared instance of singleton bean '" + beanName + "'"); sharedInstance = createBean(beanName, mergedBeanDefinition); addSingleton(beanName, sharedInstance); } } return getObjectForSharedInstance(name, sharedInstance); } else {//如果不是配置成單例,則建立物件 return createBean(name, mergedBeanDefinition);//建立物件 } } }
這裡只是先對name進行轉換(這裡涉及FactoryBean,後面會專門講解),然後從單例的map裡查,如果有則返回,沒有就從xml載入配置的類的資訊,封裝在RootBeanDefinition 裡(以後部落格會分析BeanDefinition),到這裡還是沒講怎麼建立物件,建立過程在createBean(name, mergedBeanDefinition)方法裡,createBean是在AbstractAutowireCapableBeanFactory的抽象類裡實現的。
AbstractAutowireCapableBeanFactory的createBean方法
protected Object createBean(String beanName, RootBeanDefinition mergedBeanDefinition) throws BeansException { if (logger.isDebugEnabled()) { logger.debug("Creating instance of bean '" + beanName + "' with merged definition [" + mergedBeanDefinition + "]"); } if (mergedBeanDefinition.getDependsOn() != null) {//判斷是否配置依賴,有則先建立依賴的物件 for (int i = 0; i < mergedBeanDefinition.getDependsOn().length; i++) { // guarantee initialization of beans that the current one depends on getBean(mergedBeanDefinition.getDependsOn()[i]); } } BeanWrapper instanceWrapper = null;//BeanWrapper這個是建立物件的包裝類 if (mergedBeanDefinition.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR || mergedBeanDefinition.hasConstructorArgumentValues()) {//判斷是否通過構造方法建立的,如果是則裝配構造方法引數沒返回BeanWrapper instanceWrapper = autowireConstructor(beanName, mergedBeanDefinition); } else {//如果沒有配置構造方法的引數 instanceWrapper = new BeanWrapperImpl(mergedBeanDefinition.getBeanClass());//new BeanWrapper initBeanWrapper(instanceWrapper);//設定自定義屬性 } Object bean = instanceWrapper.getWrappedInstance();//直接通過無參的方式new物件,好了物件創建出來了 //如果是單列放到單例的map裡 if (mergedBeanDefinition.isSingleton()) { addSingleton(beanName, bean); } populateBean(beanName, mergedBeanDefinition, instanceWrapper);//設定物件的屬性 //判斷是否Aware,這後面會專門講 try { if (bean instanceof BeanNameAware) { if (logger.isDebugEnabled()) { logger.debug("Invoking setBeanName() on BeanNameAware bean '" + beanName + "'"); } ((BeanNameAware) bean).setBeanName(beanName); } if (bean instanceof BeanFactoryAware) { if (logger.isDebugEnabled()) { logger.debug("Invoking setBeanFactory() on BeanFactoryAware bean '" + beanName + "'"); } ((BeanFactoryAware) bean).setBeanFactory(this); } bean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);//執行初始化前執行的自定義方法 invokeInitMethods(bean, beanName, mergedBeanDefinition);//執行初始化方法 bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);//執行初始化後執行的自定義方法 } catch (InvocationTargetException ex) { throw new BeanCreationException(mergedBeanDefinition.getResourceDescription(), beanName, "Initialization of bean failed", ex.getTargetException()); } catch (Exception ex) { throw new BeanCreationException(mergedBeanDefinition.getResourceDescription(), beanName, "Initialization of bean failed", ex); } return bean; }
這裡主要講通過RootBeanDefinition來建立物件,設定物件的屬性值。建立物件是通過BeanWrapper 來實現的。其實new物件時很簡單的,就用反射例項無參的構造方法,這裡複雜的是設定物件屬性,設定屬性有兩種方式:構造方法,set方法,其實也是通過反射實現的,具體的實現都在BeanWrapper裡,有興趣的可以自己去看,因為這裡細節太多就不展開了。
這裡只講解了怎麼創建出一個物件,但怎麼載入類的資訊的呢?請看下篇部落格。