4、Spring之Bean生命周期~获取Bean
- 获取Bean
- transformedBeanName()方法
- BeanFactoryUtils的transformedBeanName方法
- canonicalName()方法
- getObjectForBeanInstance()方法
- getObjectFromFactoryBean()方法
获取Bean
Spring Bean的生命周期首先会经过扫描,然后回经过合并,合并之后就会通过getBean()方法去获取bean,getBean()方法大致逻辑,先根据判断是单例bean还是原型bean,原型bean直接创建,单例bean会判断单例池中有没有,没有的话再去创建。废话不多说,直接上代码:
/*** Return an instance, which may be shared or independent, of the specified bean.** @param name the name of the bean to retrieve* @param requiredType the required type of the bean to retrieve* @param args arguments to use when creating a bean instance using explicit arguments* (only applied when creating a new instance as opposed to retrieving an existing one)* @param typeCheckOnly whether the instance is obtained for a type check,* not for actual use* @return an instance of the bean* @throws BeansException if the bean could not be created*/
@SuppressWarnings("unchecked")
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)throws BeansException {// name有可能是 &xxx 或者 xxx,如果name是&xxx,那么beanName就是xxx// name有可能传入进来的是别名,那么beanName就是id// 拿到真正的beanNameString beanName = transformedBeanName(name);Object beanInstance;// Eagerly check singleton cache for manually registered singletons.// 先判断单例池中是否存在 再判断二级缓存是否存在 再判断三级缓存是否存在Object sharedInstance = 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 + "'");}}// 如果sharedInstance是FactoryBean,那么就调用getObject()返回对象beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);} else {// Fail if we're already creating this bean instance:// We're assumably within a circular reference.// 判断是否是正在创建的原型bean 这里用到啦ThreadLocalif (isPrototypeCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName);}// Check if bean definition exists in this factory.BeanFactory parentBeanFactory = getParentBeanFactory();// 如果 父BeanFactory有值 且 BeanDefinition不存在if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {// Not found -> check parent.// &&&&xxx---->&xxxString 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.return (T) parentBeanFactory.getBean(nameToLookup, args);} else if (requiredType != null) {// No args -> delegate to standard getBean method.return parentBeanFactory.getBean(nameToLookup, requiredType);} else {return (T) parentBeanFactory.getBean(nameToLookup);}}if (!typeCheckOnly) {markBeanAsCreated(beanName);}StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate").tag("beanName", name);try {if (requiredType != null) {beanCreation.tag("beanType", requiredType::toString);}// 根据 beanName 获取到合并之后的BeanDefinitionRootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);// 检查BeanDefinition是不是Abstract的checkMergedBeanDefinition(mbd, beanName, args);// Guarantee initialization of beans that the current bean depends on.String[] dependsOn = mbd.getDependsOn();if (dependsOn != null) {// dependsOn表示当前beanName所依赖的,当前Bean创建之前dependsOn所依赖的Bean必须已经创建好了for (String dep : dependsOn) {// beanName是不是被dep依赖了,如果是则出现了循环依赖if (isDependent(beanName, dep)) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");}// dep被beanName依赖了,存入dependentBeanMap中,dep为key,beanName为valueregisterDependentBean(dep, beanName);// 创建所依赖的beantry {getBean(dep);} catch (NoSuchBeanDefinitionException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"'" + beanName + "' depends on missing bean '" + dep + "'", ex);}}}// Create bean instance.if (mbd.isSingleton()) {// 单例bean创建逻辑sharedInstance = getSingleton(beanName, () -> {try {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;}});beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);} else if (mbd.isPrototype()) {// 原型bean创建逻辑// It's a prototype -> create a new instance.Object prototypeInstance = null;try {beforePrototypeCreation(beanName);prototypeInstance = createBean(beanName, mbd, args);} finally {afterPrototypeCreation(beanName);}beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);} else {// 其他作用域bean的创建逻辑String scopeName = mbd.getScope();if (!StringUtils.hasLength(scopeName)) {throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");}Scope scope = this.scopes.get(scopeName);if (scope == null) {throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");}try { // session.getAttriute(beaName) setAttriObject scopedInstance = scope.get(beanName, () -> {beforePrototypeCreation(beanName);try {return createBean(beanName, mbd, args);} finally {afterPrototypeCreation(beanName);}});beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);} catch (IllegalStateException ex) {throw new ScopeNotActiveException(beanName, scopeName, ex);}}} catch (BeansException ex) {beanCreation.tag("exception", ex.getClass().toString());beanCreation.tag("message", String.valueOf(ex.getMessage()));cleanupAfterBeanCreationFailure(beanName);throw ex;} finally {beanCreation.end();}}// 检查通过name所获得到的beanInstance的类型是否是requiredTypereturn adaptBeanInstance(name, beanInstance, requiredType);
}
通过doGetBean方法我们可以看到:
- 首先通过transformedBeanName()方法去获取真正的beanName,因为传进来BeanName可能是别名;
- 调用getSingleton()方法判断单例池中是否存在,此方法涉及到解决循环依赖问题,详情敬请期待
- 如果单例池中存在调用getObjectForBeanInstance()方法;
- 如果单例池中不存在;
- 判断是否是正在创建中的原型Bean,如果是会报错;
- 获取BeanFactory,这里是和启动相关,不展开赘述;
- 再往下可以看到,spring.beans.instantiate,Bean的实例化;
- 调用getMergedLocalBeanDefinition()方法拿到合并之后的BeanDefinition,getMergedLocalBeanDefinition()方法在《Spring之Bean生命周期~合并BeanDefinition》有详细介绍;
- 调用checkMergedBeanDefinition()方法,判断BeanDefinition是否是抽象的;抽象的BeanDefinition不能被实例化,会报错;
- 判断是否有@DependsOn注解,如果有@DependsOn注解,先创建@DependsOn注解引用的Bean对象,如果两个Bean对象相互通过@DependsOn注解依赖,会报错;
- 再往下我们可以看到,不管scope属性是单例bean、原型Bean还是其他,都会调用createBean()方法;
- 请移步到《Spring之Bean生命周期~创建Bean》,精彩不断哦。
transformedBeanName()方法
transformedBeanName()方法详解
/*** Return the bean name, stripping out the factory dereference prefix if necessary,* and resolving aliases to canonical names.** @param name the user-specified name* @return the transformed bean name*/
protected String transformedBeanName(String name) {return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}
通过transformedBeanName方法我们可以看到,在调用canonicalName()方法之前会先调用一下BeanFactoryUtils.transformedBeanName()方法去掉BeanName开头的&(FactoryBean的BeanName是以&开头),然后再调用canonicalName()方法去获取真正的BeanName
BeanFactoryUtils的transformedBeanName方法
BeanFactoryUtils的transformedBeanName方法详解
/*** Return the actual bean name, stripping out the factory dereference* prefix (if any, also stripping repeated factory prefixes if found).* @param name the name of the bean* @return the transformed name* @see BeanFactory#FACTORY_BEAN_PREFIX*/
public static String transformedBeanName(String name) {Assert.notNull(name, "'name' must not be null");// 判断是否是以&开头,不是直接返回if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {return name;}return transformedBeanNameCache.computeIfAbsent(name, beanName -> {do {// 截取掉 & beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());}while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));return beanName;});
}
这里我们可以看到如果BeanName是以&开头的话,会截取掉开头所有的&;
回到transformedBeanName()方法;
canonicalName()方法
canonicalName()方法详解
/*** Determine the raw name, resolving aliases to canonical names.* @param name the user-specified name* @return the transformed name*/
public String canonicalName(String name) {String canonicalName = name;// Handle aliasing...String resolvedName;do {resolvedName = this.aliasMap.get(canonicalName);if (resolvedName != null) {canonicalName = resolvedName;}}while (resolvedName != null);return canonicalName;
}
通过canonicalName()方法我们可以看到,会不断地从aliasMap中回去,直到获取到的是null,说明是真正的BeanName;
aliasMap的结构:<别名,真正的BeanName>
回到doGetBean()方法
getObjectForBeanInstance()方法
getObjectForBeanInstance()方法详解
/*** Get the object for the given bean instance, either the bean* instance itself or its created object in case of a FactoryBean.** @param beanInstance the shared bean instance* @param name the name that may include factory dereference prefix* @param beanName the canonical bean name* @param mbd the merged bean definition* @return the object to expose for the bean*/
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.// 如果&xxx,那么就直接返回单例池中的对象if (BeanFactoryUtils.isFactoryDereference(name)) {if (beanInstance instanceof NullBean) {return beanInstance;}if (!(beanInstance instanceof FactoryBean)) {throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());}if (mbd != null) {mbd.isFactoryBean = true;}return beanInstance;}// 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.// 单例池中的对象不是FactoryBean,则直接返回if (!(beanInstance instanceof FactoryBean)) {return beanInstance;}/*** name中不包含& 且 bean对象实现啦FactoryBean接口* 说明要获取FactoryBean的getObject方法返回的对象* */Object object = null;if (mbd != null) {mbd.isFactoryBean = true;} else {// 从factoryBeanObjectCache中直接拿对象object = getCachedObjectForFactoryBean(beanName);}if (object == null) {// Return bean instance from factory.FactoryBean<?> factory = (FactoryBean<?>) beanInstance;// Caches object obtained from FactoryBean if it is a singleton.if (mbd == null && containsBeanDefinition(beanName)) {mbd = getMergedLocalBeanDefinition(beanName);}// synthetic为true,表示这个Bean不是正常的一个Bean,可能只是起到辅助作用的,所以这种Bean就不用去执行PostProcessor了boolean synthetic = (mbd != null && mbd.isSynthetic());object = getObjectFromFactoryBean(factory, beanName, !synthetic);}return object;
}
通过getObjectForBeanInstance()方法我们可以看到
- 先判断调用getBean方法的传进来的name,是否是FactoryBean,如果name是&xxx,直接返回单例池中Bean对象,如果name是&xxx,但Bean对象不是FactoryBean的话会报错;
- 传进来的name不是&xxx,且不是FactoryBean说明就是普通Bean对象,直接返回单例池中的Bean对象;
- name不是以&开头且bean对象实现啦FactoryBean接口,说明要获取FactoryBean的getObject方法返回的对象;
- 首先判断factoryBeanObjectCache缓存中是否存在,存在直接返回;
- 如果还没合并BeanDefinition,先合并BeanDefinition;
- 然后调用getObjectFromFactoryBean()方法
- 回到doGetBean()方法;
getObjectFromFactoryBean()方法
getObjectFromFactoryBean()方法详解
/*** Obtain an object to expose from the given FactoryBean.** @param factory the FactoryBean instance* @param beanName the name of the bean* @param shouldPostProcess whether the bean is subject to post-processing* @return the object obtained from the FactoryBean* @throws BeanCreationException if FactoryBean object creation failed* @see org.springframework.beans.factory.FactoryBean#getObject()*/
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {if (factory.isSingleton() && containsSingleton(beanName)) {// 多个线程同时来创建就要进行控制,保证单例synchronized (getSingletonMutex()) {Object object = this.factoryBeanObjectCache.get(beanName);if (object == null) {// 执行getObject()方法,返回的object不可能为null(会返回NullBean)object = doGetObjectFromFactoryBean(factory, beanName);// Only post-process and store if not put there already during getObject() call above// (e.g. because of circular reference processing triggered by custom getBean calls)Object alreadyThere = this.factoryBeanObjectCache.get(beanName);if (alreadyThere != null) {object = alreadyThere;} else {if (shouldPostProcess) {if (isSingletonCurrentlyInCreation(beanName)) {// Temporarily return non-post-processed object, not storing it yet..return object;}beforeSingletonCreation(beanName);try {// getObject()方法返回的对象进行后置处理object = postProcessObjectFromFactoryBean(object, beanName);} catch (Throwable ex) {throw new BeanCreationException(beanName,"Post-processing of FactoryBean's singleton object failed", ex);} finally {afterSingletonCreation(beanName);}}if (containsSingleton(beanName)) {this.factoryBeanObjectCache.put(beanName, object);}}}return object;}} else {Object object = doGetObjectFromFactoryBean(factory, beanName);if (shouldPostProcess) {try {object = postProcessObjectFromFactoryBean(object, beanName);} catch (Throwable ex) {throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);}}return object;}
}
线程相关知识,这里不在展开详细赘述,通过阅读getObjectFromFactoryBean()方法我们可以看到:
- 首先判断这个Bean是单例的,且单例池中存在BeanName(这里BeanName不包含&)对应的Bean对象;
- 判断factoryBeanObjectCache缓存中是否存在,存在直接返回;
- 调用doGetObjectFromFactoryBean()方法,doGetObjectFromFactoryBean()方法会通过反射调用对象的getObject()方法;
- 回到getObjectForBeanInstance()方法中;