AbstractBeanFactory 的getBean()方法调用FactoryBean
生活随笔
收集整理的這篇文章主要介紹了
AbstractBeanFactory 的getBean()方法调用FactoryBean
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
在前面我們分析Spring IOC 容器實(shí)例化Bean 并進(jìn)行依賴注入過程的源碼時(shí),提到在getBean()方法觸發(fā)容器實(shí)例化Bean 的時(shí)候會(huì)調(diào)用AbstractBeanFactory 的doGetBean()方法來進(jìn)行實(shí)例化的過程,源碼如下:
//真正實(shí)現(xiàn)向IOC容器獲取Bean的功能,也是觸發(fā)依賴注入功能的地方 protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {//根據(jù)指定的名稱獲取被管理Bean的名稱,剝離指定名稱中對(duì)容器的相關(guān)依賴//如果指定的是別名,將別名轉(zhuǎn)換為規(guī)范的Bean名稱final String beanName = transformedBeanName(name);Object bean;// Eagerly check singleton cache for manually registered singletons.//先從緩存中取是否已經(jīng)有被創(chuàng)建過的單態(tài)類型的Bean//對(duì)于單例模式的Bean整個(gè)IOC容器中只創(chuàng)建一次,不需要重復(fù)創(chuàng)建Object sharedInstance = getSingleton(beanName);//IOC容器創(chuàng)建單例模式Bean實(shí)例對(duì)象if (sharedInstance != null && args == null) {if (logger.isDebugEnabled()) {//如果指定名稱的Bean在容器中已有單例模式的Bean被創(chuàng)建//直接返回已經(jīng)創(chuàng)建的Beanif (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的實(shí)例對(duì)象,主要是完成FactoryBean的相關(guān)處理//注意:BeanFactory是管理容器中Bean的工廠,而FactoryBean是//創(chuàng)建創(chuàng)建對(duì)象的工廠Bean,兩者之間有區(qū)別bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);}else {// Fail if we're already creating this bean instance:// We're assumably within a circular reference.//緩存沒有正在創(chuàng)建的單例模式Bean//緩存中已經(jīng)有已經(jīng)創(chuàng)建的原型模式Bean//但是由于循環(huán)引用的問題導(dǎo)致實(shí)例化對(duì)象失敗if (isPrototypeCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName);}// Check if bean definition exists in this factory.//對(duì)IOC容器中是否存在指定名稱的BeanDefinition進(jìn)行檢查,首先檢查是否//能在當(dāng)前的BeanFactory中獲取的所需要的Bean,如果不能則委托當(dāng)前容器//的父級(jí)容器去查找,如果還是找不到則沿著容器的繼承體系向父級(jí)容器查找BeanFactory parentBeanFactory = getParentBeanFactory();//當(dāng)前容器的父級(jí)容器存在,且當(dāng)前容器中不存在指定名稱的Beanif (parentBeanFactory != null && !containsBeanDefinition(beanName)) {// Not found -> check parent.//解析指定Bean名稱的原始名稱String nameToLookup = originalBeanName(name);if (parentBeanFactory instanceof AbstractBeanFactory) {return ((AbstractBeanFactory) parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);}else if (args != null) {// Delegation to parent with explicit args.//委派父級(jí)容器根據(jù)指定名稱和顯式的參數(shù)查找return (T) parentBeanFactory.getBean(nameToLookup, args);}else {// No args -> delegate to standard getBean method.//委派父級(jí)容器根據(jù)指定名稱和類型查找return parentBeanFactory.getBean(nameToLookup, requiredType);}}//創(chuàng)建的Bean是否需要進(jìn)行類型驗(yàn)證,一般不需要if (!typeCheckOnly) {//向容器標(biāo)記指定的Bean已經(jīng)被創(chuàng)建markBeanAsCreated(beanName);}try {//根據(jù)指定Bean名稱獲取其父級(jí)的Bean定義//主要解決Bean繼承時(shí)子類合并父類公共屬性問題final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);checkMergedBeanDefinition(mbd, beanName, args);// Guarantee initialization of beans that the current bean depends on.//獲取當(dāng)前Bean所有依賴Bean的名稱String[] dependsOn = mbd.getDependsOn();//如果當(dāng)前Bean有依賴Beanif (dependsOn != null) {for (String dep : dependsOn) {if (isDependent(beanName, dep)) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");}//遞歸調(diào)用getBean方法,獲取當(dāng)前Bean的依賴BeanregisterDependentBean(dep, beanName);//把被依賴Bean注冊(cè)給當(dāng)前依賴的BeangetBean(dep);}}// Create bean instance.//創(chuàng)建單例模式Bean的實(shí)例對(duì)象if (mbd.isSingleton()) {//這里使用了一個(gè)匿名內(nèi)部類,創(chuàng)建Bean實(shí)例對(duì)象,并且注冊(cè)給所依賴的對(duì)象sharedInstance = getSingleton(beanName, () -> {try {//創(chuàng)建一個(gè)指定Bean實(shí)例對(duì)象,如果有父級(jí)繼承,則合并子類和父類的定義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.//顯式地從容器單例模式Bean緩存中清除實(shí)例對(duì)象destroySingleton(beanName);throw ex;}});//獲取給定Bean的實(shí)例對(duì)象bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);}//IOC容器創(chuàng)建原型模式Bean實(shí)例對(duì)象else if (mbd.isPrototype()) {// It's a prototype -> create a new instance.//原型模式(Prototype)是每次都會(huì)創(chuàng)建一個(gè)新的對(duì)象Object prototypeInstance = null;try {//回調(diào)beforePrototypeCreation方法,默認(rèn)的功能是注冊(cè)當(dāng)前創(chuàng)建的原型對(duì)象beforePrototypeCreation(beanName);//創(chuàng)建指定Bean對(duì)象實(shí)例prototypeInstance = createBean(beanName, mbd, args);}finally {//回調(diào)afterPrototypeCreation方法,默認(rèn)的功能告訴IOC容器指定Bean的原型對(duì)象不再創(chuàng)建afterPrototypeCreation(beanName);}//獲取給定Bean的實(shí)例對(duì)象bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);}//要?jiǎng)?chuàng)建的Bean既不是單例模式,也不是原型模式,則根據(jù)Bean定義資源中//配置的生命周期范圍,選擇實(shí)例化Bean的合適方法,這種在Web應(yīng)用程序中//比較常用,如:request、session、application等生命周期else {String scopeName = mbd.getScope();final Scope scope = this.scopes.get(scopeName);//Bean定義資源中沒有配置生命周期范圍,則Bean定義不合法if (scope == null) {throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");}try {//這里又使用了一個(gè)匿名內(nèi)部類,獲取一個(gè)指定生命周期范圍的實(shí)例Object scopedInstance = scope.get(beanName, () -> {beforePrototypeCreation(beanName);try {return createBean(beanName, mbd, args);}finally {afterPrototypeCreation(beanName);}});//獲取給定Bean的實(shí)例對(duì)象bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);}catch (IllegalStateException ex) {throw new BeanCreationException(beanName,"Scope '" + scopeName + "' is not active for the current thread; consider " +"defining a scoped proxy for this bean if you intend to refer to it from a singleton",ex);}}}catch (BeansException ex) {cleanupAfterBeanCreationFailure(beanName);throw ex;}}// Check if required type matches the type of the actual bean instance.//對(duì)創(chuàng)建的Bean實(shí)例對(duì)象進(jìn)行類型檢查if (requiredType != null && !requiredType.isInstance(bean)) {try {T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);if (convertedBean == null) {throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());}return convertedBean;}catch (TypeMismatchException ex) {if (logger.isDebugEnabled()) {logger.debug("Failed to convert bean '" + name + "' to required type '" +ClassUtils.getQualifiedName(requiredType) + "'", ex);}throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());}}return (T) bean; } //獲取給定Bean的實(shí)例對(duì)象,主要是完成FactoryBean的相關(guān)處理 protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {// Don't let calling code try to dereference the factory if the bean isn't a factory.//容器已經(jīng)得到了Bean實(shí)例對(duì)象,這個(gè)實(shí)例對(duì)象可能是一個(gè)普通的Bean,//也可能是一個(gè)工廠Bean,如果是一個(gè)工廠Bean,則使用它創(chuàng)建一個(gè)Bean實(shí)例對(duì)象,//如果調(diào)用本身就想獲得一個(gè)容器的引用,則指定返回這個(gè)工廠Bean實(shí)例對(duì)象//如果指定的名稱是容器的解引用(dereference,即是對(duì)象本身而非內(nèi)存地址),//且Bean實(shí)例也不是創(chuàng)建Bean實(shí)例對(duì)象的工廠Beanif (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());}// Now we have the bean instance, which may be a normal bean or a FactoryBean.// If it's a FactoryBean, we use it to create a bean instance, unless the// caller actually wants a reference to the factory.//如果Bean實(shí)例不是工廠Bean,或者指定名稱是容器的解引用,//調(diào)用者向獲取對(duì)容器的引用,則直接返回當(dāng)前的Bean實(shí)例if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {return beanInstance;}//處理指定名稱不是容器的解引用,或者根據(jù)名稱獲取的Bean實(shí)例對(duì)象是一個(gè)工廠Bean//使用工廠Bean創(chuàng)建一個(gè)Bean的實(shí)例對(duì)象Object object = null;if (mbd == null) {//從Bean工廠緩存中獲取給定名稱的Bean實(shí)例對(duì)象object = getCachedObjectForFactoryBean(beanName);}//讓Bean工廠生產(chǎn)給定名稱的Bean對(duì)象實(shí)例if (object == null) {// Return bean instance from factory.FactoryBean<?> factory = (FactoryBean<?>) beanInstance;// Caches object obtained from FactoryBean if it is a singleton.//如果從Bean工廠生產(chǎn)的Bean是單態(tài)模式的,則緩存if (mbd == null && containsBeanDefinition(beanName)) {//從容器中獲取指定名稱的Bean定義,如果繼承基類,則合并基類相關(guān)屬性mbd = getMergedLocalBeanDefinition(beanName);}//如果從容器得到Bean定義信息,并且Bean定義信息不是虛構(gòu)的,//則讓工廠Bean生產(chǎn)Bean實(shí)例對(duì)象boolean synthetic = (mbd != null && mbd.isSynthetic());//調(diào)用FactoryBeanRegistrySupport類的getObjectFromFactoryBean方法,//實(shí)現(xiàn)工廠Bean生產(chǎn)Bean對(duì)象實(shí)例的過程object = getObjectFromFactoryBean(factory, beanName, !synthetic);}return object; }在上面獲取給定Bean 的實(shí)例對(duì)象的getObjectForBeanInstance() 方法中, 會(huì)調(diào)用FactoryBeanRegistrySupport 類的getObjectFromFactoryBean()方法,該方法實(shí)現(xiàn)了Bean 工廠生產(chǎn)Bean 實(shí)例對(duì)象。
Dereference(解引用):一個(gè)在C/C++中應(yīng)用比較多的術(shù)語,在C++中,”*”是解引用符號(hào),而”&”是引用符號(hào),解引用是指變量指向的是所引用對(duì)象的本身數(shù)據(jù),而不是引用對(duì)象的內(nèi)存地址。
?
?
總結(jié)
以上是生活随笔為你收集整理的AbstractBeanFactory 的getBean()方法调用FactoryBean的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: FactoryBean 源码
- 下一篇: AbstractBeanFactory