美文网首页Java
源码分析:Spring是如何获取容器中的Bean?

源码分析:Spring是如何获取容器中的Bean?

作者: 愿天堂没有BUG | 来源:发表于2022-07-04 10:03 被阅读0次

之前分析了Bean是如何注册到容器中的,既然我们把Bean交给Spring来管理,在我们需要对象的时候Spring会自动帮我们注入,那Spring肯定会有一个从容器中获取Bean的过程,只不过这个过程是Spring框架来帮我们完成的,对于我们使用者来说没有感知

下面我们就通过源码来看一下Spring是如何从容器中获取Bean的

简单的例子

首先还是从一个简单的例子来入手,XML配置方式我们一般这样获取Bean

ClassPathXmlApplicationContext applicationContext =newClassPathXmlApplicationContext("bean.xml");User user = (User) applicationContext.getBean("userBean");System.out.println(user.getUserName());

从上面的例子我们看到,Bean主要是

applicationContext.getBean()方法来获取的,我们就从ClassPathXmlApplicationContext的getBean方法来入手

publicObjectgetBean(String name)throwsBeansException{assertBeanFactoryActive();returngetBeanFactory().getBean(name);}

AbstractBeanFactory

publicObjectgetBean(String name)throwsBeansException{returndoGetBean(name,null,null,false);}

AbstractBeanFactory

protected T doGetBean(finalStringname,@Nullablefinal Class requiredType,@NullablefinalObject[] args,booleantypeCheckOnly) throws BeansException {finalStringbeanName = transformedBeanName(name);Objectbean;// 从单例缓存中获取对象ObjectsharedInstance = getSingleton(beanName);if(sharedInstance !=null&& args ==null) {if(logger.isTraceEnabled()) {if(isSingletonCurrentlyInCreation(beanName)) {logger.trace("Returning eagerly cached instance of singleton bean '"+ beanName +"' that is not fully initialized yet - a consequence of a circular reference");}else{logger.trace("Returning cached instance of singleton bean '"+ beanName +"'");}}bean = getObjectForBeanInstance(sharedInstance, name, beanName,null);}else{// Fail if we're already creating this bean instance:// We're assumably within a circular reference.if(isPrototypeCurrentlyInCreation(beanName)) {thrownewBeanCurrentlyInCreationException(beanName);}// Check if bean definition exists in this factory.BeanFactory parentBeanFactory = getParentBeanFactory();if(parentBeanFactory !=null&& !containsBeanDefinition(beanName)) {// Not found -> check parent.StringnameToLookup = originalBeanName(name);if(parentBeanFactoryinstanceofAbstractBeanFactory) {return((AbstractBeanFactory) parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);}elseif(args !=null) {// Delegation to parent with explicit args.return(T) parentBeanFactory.getBean(nameToLookup, args);}elseif(requiredType !=null) {// No args -> delegate to standard getBean method.returnparentBeanFactory.getBean(nameToLookup, requiredType);}else{return(T) parentBeanFactory.getBean(nameToLookup);}}if(!typeCheckOnly) {markBeanAsCreated(beanName);}try{//这里通过beanName获取相关信息来组装RootBeanDefinitionfinal RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);checkMergedBeanDefinition(mbd, beanName, args);// 当前Bean的依赖项String[] dependsOn = mbd.getDependsOn();if(dependsOn !=null) {for(Stringdep : dependsOn) {if(isDependent(beanName, dep)) {thrownewBeanCreationException(mbd.getResourceDescription(), beanName,"Circular depends-on relationship between '"+ beanName +"' and '"+ dep +"'");}registerDependentBean(dep, beanName);try{getBean(dep);}catch(NoSuchBeanDefinitionException ex) {thrownewBeanCreationException(mbd.getResourceDescription(), beanName,"'"+ beanName +"' depends on missing bean '"+ dep +"'", ex);}}}// 此处开始创建实例对象//单例的对象创建if(mbd.isSingleton()) {sharedInstance = getSingleton(beanName, () -> {try{returncreateBean(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);throwex;}});bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);}//多例对象的创建elseif(mbd.isPrototype()) {// It's a prototype -> create a new instance.ObjectprototypeInstance =null;try{beforePrototypeCreation(beanName);prototypeInstance = createBean(beanName, mbd, args);}finally{afterPrototypeCreation(beanName);}bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);}else{StringscopeName = mbd.getScope();final Scope scope =this.scopes.get(scopeName);if(scope ==null) {thrownewIllegalStateException("No Scope registered for scope name '"+ scopeName +"'");}try{ObjectscopedInstance = scope.get(beanName, () -> {beforePrototypeCreation(beanName);try{returncreateBean(beanName, mbd, args);}finally{afterPrototypeCreation(beanName);}});bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);}catch(IllegalStateException ex) {thrownewBeanCreationException(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);throwex;}}// Check if required type matches the type of the actual bean instance.if(requiredType !=null&& !requiredType.isInstance(bean)) {try{T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);if(convertedBean ==null) {thrownewBeanNotOfRequiredTypeException(name, requiredType, bean.getClass());}returnconvertedBean;}catch(TypeMismatchException ex) {if(logger.isTraceEnabled()) {logger.trace("Failed to convert bean '"+ name +"' to required type '"+ClassUtils.getQualifiedName(requiredType) +"'", ex);}thrownewBeanNotOfRequiredTypeException(name, requiredType, bean.getClass());}}return(T) bean;}

doGetBean()方法基本上概括了整个Bean的获取过程

首先通过BeanName从容器中获取Bean相关的信息,并组装成RootBeanDefinition

通过RootBeanDefinition来创建实例对象,这里需要根据单例、多例来分别进行创建

将创建或者获取到的对象返回

组装RootBeanDefinition

protectedRootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {// 先看看mergedBeanDefinitions中是否存在,实际上相当于缓存的作用RootBeanDefinition mbd =this.mergedBeanDefinitions.get(beanName);if(mbd !=null) {returnmbd;}//请注意此处的第二个参数,传入的是一个BeanDefinitionreturngetMergedBeanDefinition(beanName, getBeanDefinition(beanName));}

getBeanDefinition(beanName)方法返回的是一个BeanDefinition对象,我们来看一下

publicBeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {//这里通过beanName从beanDefinitionMap中获取BeanDefinationBeanDefinition bd =this.beanDefinitionMap.get(beanName);if(bd ==null) {if(logger.isTraceEnabled()) {logger.trace("No bean named '"+ beanName +"' found in "+this);}thrownew NoSuchBeanDefinitionException(beanName);}returnbd;}

getBeanDefinition()方法的作用就是从beanDefinitionMap中获取BeanDefinition,这里有没有很熟悉的感觉?Bean在注册到容器中的时候,就是存入到beanDefinitionMap中,这里来进行获取,两边相当于对上了。

我们继续来看一下getMergedBeanDefinition()方法

protectedRootBeanDefinitiongetMergedBeanDefinition(

String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)throwsBeanDefinitionStoreException{synchronized(this.mergedBeanDefinitions) {RootBeanDefinition mbd =null;// Check with full lock now in order to enforce the same merged instance.if(containingBd ==null) {//从缓存中获取RootBeanDefinitionmbd =this.mergedBeanDefinitions.get(beanName);}if(mbd ==null) {if(bd.getParentName() ==null) {// Use copy of given root bean definition.if(bdinstanceofRootBeanDefinition) {mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();}else{//这里通过BeanDefinition来创建一个RootBeanDefinitionmbd =newRootBeanDefinition(bd);}}else{// Child bean definition: needs to be merged with parent.BeanDefinition pbd;try{String parentBeanName = transformedBeanName(bd.getParentName());if(!beanName.equals(parentBeanName)) {pbd = getMergedBeanDefinition(parentBeanName);}else{BeanFactory parent = getParentBeanFactory();if(parentinstanceofConfigurableBeanFactory) {pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);}else{thrownewNoSuchBeanDefinitionException(parentBeanName,"Parent name '"+ parentBeanName +"' is equal to bean name '"+ beanName +"': cannot be resolved without an AbstractBeanFactory parent");}}}catch(NoSuchBeanDefinitionException ex) {thrownewBeanDefinitionStoreException(bd.getResourceDescription(), beanName,"Could not resolve parent bean definition '"+ bd.getParentName() +"'", ex);}// Deep copy with overridden values.mbd =newRootBeanDefinition(pbd);mbd.overrideFrom(bd);}// 设置默认为单例if(!StringUtils.hasLength(mbd.getScope())) {mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON);}// A bean contained in a non-singleton bean cannot be a singleton itself.// Let's correct this on the fly here, since this might be the result of// parent-child merging for the outer bean, in which case the original inner bean// definition will not have inherited the merged outer bean's singleton status.if(containingBd !=null&& !containingBd.isSingleton() && mbd.isSingleton()) {mbd.setScope(containingBd.getScope());}//将构建好的RootBeanDefinition进行缓存if(containingBd ==null&& isCacheBeanMetadata()) {this.mergedBeanDefinitions.put(beanName, mbd);}}returnmbd;}}

创建对象实例

上面构造好了RootBeanDefinition,下面来创建对象

//单例对象的创建if(mbd.isSingleton()) {sharedInstance = getSingleton(beanName, () -> {try{returncreateBean(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);throwex;}});bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);}

protectedObjectcreateBean(StringbeanName, RootBeanDefinition mbd,@NullableObject[] args)throws BeanCreationException {if(logger.isTraceEnabled()) {logger.trace("Creating instance of bean '"+ beanName +"'");}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 =newRootBeanDefinition(mbd);mbdToUse.setBeanClass(resolvedClass);}// Prepare method overrides.try{mbdToUse.prepareMethodOverrides();}catch(BeanDefinitionValidationException ex) {thrownewBeanDefinitionStoreException(mbdToUse.getResourceDescription(),beanName,"Validation of method overrides failed", ex);}try{// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.Objectbean = resolveBeforeInstantiation(beanName, mbdToUse);if(bean !=null) {returnbean;}}catch(Throwable ex) {thrownewBeanCreationException(mbdToUse.getResourceDescription(), beanName,"BeanPostProcessor before instantiation of bean failed", ex);}try{//根据beanName创建对象ObjectbeanInstance = doCreateBean(beanName, mbdToUse, args);if(logger.isTraceEnabled()) {logger.trace("Finished creating instance of bean '"+ beanName +"'");}returnbeanInstance;}catch(BeanCreationException | ImplicitlyAppearedSingletonException ex) {// A previously detected exception with proper bean creation context already,// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.throwex;}catch(Throwable ex) {thrownewBeanCreationException(mbdToUse.getResourceDescription(), beanName,"Unexpected exception during bean creation", ex);}}

protectedObjectdoCreateBean(finalStringbeanName, final RootBeanDefinition mbd, final@NullableObject[] args)throws BeanCreationException {// 初始化BeanBeanWrapper instanceWrapper =null;if(mbd.isSingleton()) {instanceWrapper =this.factoryBeanInstanceCache.remove(beanName);}if(instanceWrapper ==null) {//创建Bean实例instanceWrapper = createBeanInstance(beanName, mbd, args);}finalObjectbean = instanceWrapper.getWrappedInstance();Class beanType = instanceWrapper.getWrappedClass();if(beanType != NullBean.class) {mbd.resolvedTargetType = beanType;}// Allow post-processors to modify the merged bean definition.synchronized (mbd.postProcessingLock) {if(!mbd.postProcessed) {try{applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);}catch(Throwable ex) {thrownewBeanCreationException(mbd.getResourceDescription(), beanName,"Post-processing of merged bean definition failed", ex);}mbd.postProcessed =true;}}// Eagerly cache singletons to be able to resolve circular references// even when triggered by lifecycle interfaces like BeanFactoryAware.booleanearlySingletonExposure = (mbd.isSingleton() &&this.allowCircularReferences &&isSingletonCurrentlyInCreation(beanName));if(earlySingletonExposure) {if(logger.isTraceEnabled()) {logger.trace("Eagerly caching bean '"+ beanName +"' to allow for resolving potential circular references");}addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));}// Initialize the bean instance.ObjectexposedObject = bean;try{populateBean(beanName, mbd, instanceWrapper);exposedObject = initializeBean(beanName, exposedObject, mbd);}catch(Throwable ex) {if(exinstanceofBeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {throw(BeanCreationException) ex;}else{thrownewBeanCreationException(mbd.getResourceDescription(), beanName,"Initialization of bean failed", ex);}}if(earlySingletonExposure) {ObjectearlySingletonReference = getSingleton(beanName,false);if(earlySingletonReference !=null) {if(exposedObject == bean) {exposedObject = earlySingletonReference;}elseif(!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {String[] dependentBeans = getDependentBeans(beanName);Set actualDependentBeans =newLinkedHashSet<>(dependentBeans.length);for(StringdependentBean : dependentBeans) {if(!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {actualDependentBeans.add(dependentBean);}}if(!actualDependentBeans.isEmpty()) {thrownewBeanCurrentlyInCreationException(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.try{registerDisposableBeanIfNecessary(beanName, bean, mbd);}catch(BeanDefinitionValidationException ex) {thrownewBeanCreationException(mbd.getResourceDescription(), beanName,"Invalid destruction signature", ex);}returnexposedObject;}

protectedBeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd,@NullableObject[] args) {// Make sure bean class is actually resolved at this point.Class beanClass = resolveBeanClass(mbd, beanName);if(beanClass !=null&& !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {thrownew BeanCreationException(mbd.getResourceDescription(), beanName,"Bean class isn't public, and non-public access not allowed: "+ beanClass.getName());}Supplier instanceSupplier = mbd.getInstanceSupplier();if(instanceSupplier !=null) {returnobtainFromSupplier(instanceSupplier, beanName);}if(mbd.getFactoryMethodName() !=null) {//使用FactotyMethod实例化BeanreturninstantiateUsingFactoryMethod(beanName, mbd, args);}// Shortcut when re-creating the same bean...boolean resolved =false;boolean autowireNecessary =false;if(args ==null) {synchronized (mbd.constructorArgumentLock) {if(mbd.resolvedConstructorOrFactoryMethod !=null) {resolved =true;autowireNecessary = mbd.constructorArgumentsResolved;}}}if(resolved) {if(autowireNecessary) {returnautowireConstructor(beanName, mbd,null,null);}else{returninstantiateBean(beanName, mbd);}}// Candidate constructors for autowiring?Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);if(ctors !=null|| mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {returnautowireConstructor(beanName, mbd, ctors, args);}// Preferred constructors for default construction?ctors = mbd.getPreferredConstructors();if(ctors !=null) {returnautowireConstructor(beanName, mbd, ctors,null);}// No special handling: simply use no-arg constructor.returninstantiateBean(beanName, mbd);}

上面可以看到,通过不同的方法进行Bean的实例化,有FactoryMethod、autowireConstructor、还有无参构造器,这里看一下通过FactoryMethod的实例化

protectedBeanWrapperinstantiateUsingFactoryMethod(String beanName, RootBeanDefinition mbd,@NullableObject[] explicitArgs) {returnnewConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);}

publicBeanWrapper instantiateUsingFactoryMethod(StringbeanName, RootBeanDefinition mbd,@NullableObject[] explicitArgs) {BeanWrapperImpl bw =newBeanWrapperImpl();this.beanFactory.initBeanWrapper(bw);ObjectfactoryBean;Class factoryClass;booleanisStatic;//获取FactoryBeanNameStringfactoryBeanName = mbd.getFactoryBeanName();if(factoryBeanName !=null) {if(factoryBeanName.equals(beanName)) {thrownewBeanDefinitionStoreException(mbd.getResourceDescription(), beanName,"factory-bean reference points back to the same bean definition");}//从容器中获取factoryBeanfactoryBean =this.beanFactory.getBean(factoryBeanName);if(mbd.isSingleton() &&this.beanFactory.containsSingleton(beanName)) {thrownewImplicitlyAppearedSingletonException();}//实例化factoryClassfactoryClass = factoryBean.getClass();isStatic =false;}else{// It's a static factory method on the bean class.if(!mbd.hasBeanClass()) {thrownewBeanDefinitionStoreException(mbd.getResourceDescription(), beanName,"bean definition declares neither a bean class nor a factory-bean reference");}factoryBean =null;factoryClass = mbd.getBeanClass();isStatic =true;}Method factoryMethodToUse =null;ArgumentsHolder argsHolderToUse =null;Object[] argsToUse =null;if(explicitArgs !=null) {argsToUse = explicitArgs;}else{Object[] argsToResolve =null;synchronized (mbd.constructorArgumentLock) {factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;if(factoryMethodToUse !=null&& mbd.constructorArgumentsResolved) {// Found a cached factory method...argsToUse = mbd.resolvedConstructorArguments;if(argsToUse ==null) {argsToResolve = mbd.preparedConstructorArguments;}}}if(argsToResolve !=null) {argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve,true);}}if(factoryMethodToUse ==null|| argsToUse ==null) {// Need to determine the factory method...// Try all methods with this name to see if they match the given arguments.factoryClass = ClassUtils.getUserClass(factoryClass);Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);List candidateList =newArrayList<>();//过滤出工厂方法for(Method candidate : rawCandidates) {if(Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {candidateList.add(candidate);}}if(candidateList.size() ==1&& explicitArgs ==null&& !mbd.hasConstructorArgumentValues()) {Method uniqueCandidate = candidateList.get(0);if(uniqueCandidate.getParameterCount() ==0) {mbd.factoryMethodToIntrospect = uniqueCandidate;synchronized (mbd.constructorArgumentLock) {mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;mbd.constructorArgumentsResolved =true;mbd.resolvedConstructorArguments = EMPTY_ARGS;}//使用工厂方法创建实例对象bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, uniqueCandidate, EMPTY_ARGS));returnbw;}}Method[] candidates = candidateList.toArray(newMethod[0]);AutowireUtils.sortFactoryMethods(candidates);ConstructorArgumentValues resolvedValues =null;booleanautowiring = (mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);int minTypeDiffWeight = Integer.MAX_VALUE;Set ambiguousFactoryMethods =null;int minNrOfArgs;if(explicitArgs !=null) {minNrOfArgs = explicitArgs.length;}else{// We don't have arguments passed in programmatically, so we need to resolve the// arguments specified in the constructor arguments held in the bean definition.if(mbd.hasConstructorArgumentValues()) {ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();resolvedValues =newConstructorArgumentValues();minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);}else{minNrOfArgs =0;}}/************因代码太长,略过很多代码*******************************

}

privateObject instantiate(String beanName, RootBeanDefinition mbd,@NullableObject factoryBean, Method factoryMethod, Object[] args) {try{if(System.getSecurityManager() !=null) {returnAccessController.doPrivileged((PrivilegedAction) () ->this.beanFactory.getInstantiationStrategy().instantiate(mbd, beanName,this.beanFactory, factoryBean, factoryMethod, args),this.beanFactory.getAccessControlContext());}else{//创建实例对象returnthis.beanFactory.getInstantiationStrategy().instantiate(mbd, beanName,this.beanFactory, factoryBean, factoryMethod, args);}}catch(Throwable ex) {thrownew BeanCreationException(mbd.getResourceDescription(), beanName,"Bean instantiation via factory method failed", ex);}}

publicObjectinstantiate(RootBeanDefinition bd,@NullableStringbeanName, BeanFactory owner,@NullableObjectfactoryBean, final Method factoryMethod,Object... args) {try{if(System.getSecurityManager() !=null) {AccessController.doPrivileged((PrivilegedAction) () -> {ReflectionUtils.makeAccessible(factoryMethod);returnnull;});}else{ReflectionUtils.makeAccessible(factoryMethod);}Method priorInvokedFactoryMethod = currentlyInvokedFactoryMethod.get();try{currentlyInvokedFactoryMethod.set(factoryMethod);//这里使用反射调用工厂方法,生成对象并返回Objectresult = factoryMethod.invoke(factoryBean, args);if(result ==null) {result =newNullBean();}returnresult;}finally{if(priorInvokedFactoryMethod !=null) {currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod);}else{currentlyInvokedFactoryMethod.remove();}}}catch(IllegalArgumentException ex) {thrownewBeanInstantiationException(factoryMethod,"Illegal arguments to factory method '"+ factoryMethod.getName() +"'; "+"args: "+ StringUtils.arrayToCommaDelimitedString(args), ex);}catch(IllegalAccessException ex) {thrownewBeanInstantiationException(factoryMethod,"Cannot access factory method '"+ factoryMethod.getName() +"'; is it public?", ex);}catch(InvocationTargetException ex) {Stringmsg ="Factory method '"+ factoryMethod.getName() +"' threw exception";if(bd.getFactoryBeanName() !=null&& ownerinstanceofConfigurableBeanFactory &&((ConfigurableBeanFactory) owner).isCurrentlyInCreation(bd.getFactoryBeanName())) {msg ="Circular reference involving containing bean '"+ bd.getFactoryBeanName() +"' - consider "+"declaring the factory method as static for independence from its containing instance. "+ msg;}thrownewBeanInstantiationException(factoryMethod, msg, ex.getTargetException());}}

使用反射调用工厂方法,生成对象并返回,返回对象就表示从容器中根据注册的Bean信息拿到了具体的对象,到此整个调用链路都完成了。

我原本以为是在调用getBean()时才去进行Bean的实例化,但是在断点跟踪的过程中,发现单例对象实际上是在容器启动的时候就会去实例化,getBean()的时候直接拿,不用再实例化。代码如下:

publicvoidrefresh()throwsBeansException, IllegalStateException{synchronized(this.startupShutdownMonitor) {// Prepare this context for refreshing.prepareRefresh();// Tell the subclass to refresh the internal bean factory.ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// Prepare the bean factory for use in this context.prepareBeanFactory(beanFactory);try{// Allows post-processing of the bean factory in context subclasses.postProcessBeanFactory(beanFactory);// Invoke factory processors registered as beans in the context.invokeBeanFactoryPostProcessors(beanFactory);// Register bean processors that intercept bean creation.registerBeanPostProcessors(beanFactory);// Initialize message source for this context.initMessageSource();// Initialize event multicaster for this context.initApplicationEventMulticaster();// Initialize other special beans in specific context subclasses.onRefresh();// Check for listener beans and register them.registerListeners();// Instantiate all remaining (non-lazy-init) singletons.finishBeanFactoryInitialization(beanFactory);// Last step: publish corresponding event.finishRefresh();}catch(BeansException ex) {if(logger.isWarnEnabled()) {logger.warn("Exception encountered during context initialization - "+"cancelling refresh attempt: "+ ex);}// Destroy already created singletons to avoid dangling resources.destroyBeans();// Reset 'active' flag.cancelRefresh(ex);// Propagate exception to caller.throwex;}finally{// Reset common introspection caches in Spring's core, since we// might not ever need metadata for singleton beans anymore...resetCommonCaches();}}}

在refresh()方法中有专门进行单例初始化的方法,就是

finishBeanFactoryInitialization(beanFactory),从注释可以看出来就是用来做单例的实例化的

protectedvoidfinishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory){// Initialize conversion service for this context.if(beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)){beanFactory.setConversionService(beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));}// Register a default embedded value resolver if no bean post-processor// (such as a PropertyPlaceholderConfigurer bean) registered any before:// at this point, primarily for resolution in annotation attribute values.if(!beanFactory.hasEmbeddedValueResolver()) {beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));}// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class,false,false);for(String weaverAwareName : weaverAwareNames) {getBean(weaverAwareName);}// Stop using the temporary ClassLoader for type matching.beanFactory.setTempClassLoader(null);// Allow for caching all bean definition metadata, not expecting further changes.beanFactory.freezeConfiguration();// 实例化单例对象beanFactory.preInstantiateSingletons();}

publicvoidpreInstantiateSingletons() throws BeansException {if(logger.isTraceEnabled()) {logger.trace("Pre-instantiating singletons in "+this);}// Iterate over a copy to allow for init methods which in turn register new bean definitions.// While this may not be part of the regular factory bootstrap, it does otherwise work fine.List beanNames =newArrayList<>(this.beanDefinitionNames);// Trigger initialization of all non-lazy singleton beans...for(StringbeanName : beanNames) {RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);if(!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {if(isFactoryBean(beanName)) {Objectbean = getBean(FACTORY_BEAN_PREFIX + beanName);if(beaninstanceofFactoryBean) {final FactoryBean factory = (FactoryBean) bean;booleanisEagerInit;if(System.getSecurityManager() !=null&& factoryinstanceofSmartFactoryBean) {isEagerInit = AccessController.doPrivileged((PrivilegedAction)((SmartFactoryBean) factory)::isEagerInit,getAccessControlContext());}else{isEagerInit = (factoryinstanceofSmartFactoryBean &&((SmartFactoryBean) factory).isEagerInit());}if(isEagerInit) {getBean(beanName);}}}else{//从这里可以看出来,单例的实例化是通过调用getBean方法来实现的getBean(beanName);}}}// Trigger post-initialization callback for all applicable beans...for(StringbeanName : beanNames) {ObjectsingletonInstance = getSingleton(beanName);if(singletonInstanceinstanceofSmartInitializingSingleton) {final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;if(System.getSecurityManager() !=null) {AccessController.doPrivileged((PrivilegedAction) () -> {smartSingleton.afterSingletonsInstantiated();returnnull;}, getAccessControlContext());}else{smartSingleton.afterSingletonsInstantiated();}}}}

从上面的代码可以看出来,容器在启动的时候就会实例化单例对象,并且还是调用的getBean()方法做的实例化,当你从容器中获取Bean的时候,就直接取现成的对象了

protectedObject getSingleton(String beanName, boolean allowEarlyReference) {//从singletonObjects中获取已经实例化好的对象Object singletonObject =this.singletonObjects.get(beanName);if(singletonObject ==null&& isSingletonCurrentlyInCreation(beanName)) {synchronized (this.singletonObjects) {singletonObject =this.earlySingletonObjects.get(beanName);if(singletonObject ==null&& allowEarlyReference) {ObjectFactory singletonFactory =this.singletonFactories.get(beanName);if(singletonFactory !=null) {singletonObject = singletonFactory.getObject();this.earlySingletonObjects.put(beanName, singletonObject);this.singletonFactories.remove(beanName);}}}}returnsingletonObject;}

以上就是从容器中获取单例Bean的过程,多例也是差不多的过程,就不再赘述,有兴趣可以自己研究一下

总结一下

Spring从容器中获取Bean的过程如下:

首先通过BeanName从容器中获取Bean相关的信息,并组装成RootBeanDefinition

通过RootBeanDefinition来创建实例对象,这里需要根据单例、多例来分别进行创建

单例对象是容器启动的时候就已经实例化好了,可以直接拿来用,当然你也可以设置延迟加载

相关文章

网友评论

    本文标题:源码分析:Spring是如何获取容器中的Bean?

    本文链接:https://www.haomeiwen.com/subject/wikdbrtx.html