前言
大家使用spring,最常接触到的就是bean,大家也知道spring中用一句getBean就能取出一个实例化好的bean,这个bean是属于IOC容器管理的,那么大家有没有看过getBean方法的源码呢,知不知道spring容器到底是怎么得到一个实例化好的bean的呢,这一次,我和大家一起来研究getBean方法的源码
开始
首先我来一段非常简单的代码
//我是用注解方式配置的applicationContext,Appconfig就是配置类,用来扫描bean的
AnnotationConfigApplicationContext annotationConfigApplicationContext= new AnnotationConfigApplicationContext(Appconfig.class);
annotationConfigApplicationContext.getBean(IndexService.class)
接着我们点到getBean方法里面,可以看到一开始进到了org.springframework.context.support.AbstractApplicationContext#getBean(java.lang.Class<T>)
@Override
public <T> T getBean(Class<T> requiredType) throws BeansException {//assertBeanFactoryActive();return getBeanFactory().getBean(requiredType);
}
然后我们看这里的这个getBean,实际上是调用了org.springframework.beans.factory.support.DefaultListableBeanFactory#getBean(java.lang.Class<T>)这个getBean方法
@Override
public <T> T getBean(Class<T> requiredType) throws BeansException {/*** getBean 是一个空壳方法,所有的逻辑都封装在 doGetBean 方法中,等一下会看到*/return getBean(requiredType, (Object[]) null);
}
这个DefaultListableBeanFactory很重要,我们知道spring IOC的顶层接口实际上是BeanFactory,而真正能作为独立的ioc容器使用的还是DefaultListableBeanFactory,我们来看下整体类图

可以看到DefaultListableBeanFactory继承了ConfigureableListableBeanFactory接口,BeanDefinitionRegistry接口(bean定义的注册接口),并继承AutowireCapableBeanFactory,实现全部类管理的功能。DefaultListableBeanFactory其实要实现的功能就是以list集合的方式操作bean,最典型的应用是:在访问bean前,先注册所有的definition(可能从bean definition配置文件中)。使用预先建立的bean定义元数据对象,从本地的bean definition表中查询bean definition因而将不会花费太多成本。今天我们的重点不在DefaultListableBeanFactory这个类上,所以就不展开研究这个类了,我们接下去看
@Overridepublic <T> T getBean(Class<T> requiredType, @Nullable Object... args) throws BeansException {//NamedBeanHolder 可以理解为一个数据结构和map差不多,里面就是存了bean的名字和bean的实例//A simple holder for a given bean name plus bean instance//一个简单的bean和名字的容器//通过resolveNamedBean方法得到这个holderNamedBeanHolder<T> namedBean = resolveNamedBean(requiredType, args);if (namedBean != null) {//获取有名字的Bean的实例return namedBean.getBeanInstance();}//上层Bean工厂BeanFactory parent = getParentBeanFactory();if (parent != null) {return (args != null ? parent.getBean(requiredType, args) : parent.getBean(requiredType));}throw new NoSuchBeanDefinitionException(requiredType);}
我们看一下NamedBeanHolder这个类是怎么定义的
/*** A simple holder for a given bean name plus bean instance.** @author Juergen Hoeller* @since 4.3.3* @see AutowireCapableBeanFactory#resolveNamedBean(Class)*/
public class NamedBeanHolder<T> implements NamedBean {private final String beanName;private final T beanInstance;/*** Create a new holder for the given bean name plus instance.* @param beanName the name of the bean* @param beanInstance the corresponding bean instance*/public NamedBeanHolder(String beanName, T beanInstance) {Assert.notNull(beanName, "Bean name must not be null");this.beanName = beanName;this.beanInstance = beanInstance;}/*** Return the name of the bean.*/@Overridepublic String getBeanName() {return this.beanName;}/*** Return the corresponding bean instance.*/public T getBeanInstance() {return this.beanInstance;}}
这里的getBean的关键代码在于resolveNamedBean(requiredType, args),这段代码获得了这个holder,其实也就是获得了bean的名字和bean的实例,那么这里就要具体看一下是怎么获得的bean名字和bean实例了。废话不多上代码
@SuppressWarnings("unchecked")@Nullableprivate <T> NamedBeanHolder<T> resolveNamedBean(Class<T> requiredType, @Nullable Object... args) throws BeansException {Assert.notNull(requiredType, "Required type must not be null");//得到可能的bean名字数组String[] candidateNames = getBeanNamesForType(requiredType);/*** 得到对象的名字,因为对象可能有别名所以需要处理别名*/if (candidateNames.length > 1) {List<String> autowireCandidates = new ArrayList<>(candidateNames.length);for (String beanName : candidateNames) {if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) {autowireCandidates.add(beanName);}}if (!autowireCandidates.isEmpty()) {candidateNames = StringUtils.toStringArray(autowireCandidates);}}if (candidateNames.length == 1) {String beanName = candidateNames[0];//这的getBean才是真正获取对象的方法return new NamedBeanHolder<>(beanName, getBean(beanName, requiredType, args));}else if (candidateNames.length > 1) {Map<String, Object> candidates = new LinkedHashMap<>(candidateNames.length);for (String beanName : candidateNames) {if (containsSingleton(beanName) && args == null) {Object beanInstance = getBean(beanName);candidates.put(beanName, (beanInstance instanceof NullBean ? null : beanInstance));}else {candidates.put(beanName, getType(beanName));}}String candidateName = determinePrimaryCandidate(candidates, requiredType);if (candidateName == null) {candidateName = determineHighestPriorityCandidate(candidates, requiredType);}if (candidateName != null) {Object beanInstance = candidates.get(candidateName);if (beanInstance == null || beanInstance instanceof Class) {beanInstance = getBean(candidateName, requiredType, args);}return new NamedBeanHolder<>(candidateName, (T) beanInstance);}throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet());}return null;}
在这一段代码中,我们首先要看String[] candidateNames = getBeanNamesForType(requiredType);这句代码,这个方法进去之后其实会调用很多层
@Overridepublic String[] getBeanNamesForType(@Nullable Class<?> type) {return getBeanNamesForType(type, true, true);}@Overridepublic String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {if (!isConfigurationFrozen() || type == null || !allowEagerInit) {//这句代码才是真正通过类型获取名字的代码return doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, allowEagerInit);}Map<Class<?>, String[]> cache =(includeNonSingletons ? this.allBeanNamesByType : this.singletonBeanNamesByType);String[] resolvedBeanNames = cache.get(type);if (resolvedBeanNames != null) {return resolvedBeanNames;}resolvedBeanNames = doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, true);if (ClassUtils.isCacheSafe(type, getBeanClassLoader())) {cache.put(type, resolvedBeanNames);}return resolvedBeanNames;}//根据类型去factory中获取对应类的名字//比如在工厂初始化的时候可以根据BeanFactory去获取所有的BeanFactoryProcessorprivate String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {List<String> result = new ArrayList<>();// Check all bean definitions.for (String beanName : this.beanDefinitionNames) {// Only consider bean as eligible if the bean name// is not defined as alias for some other bean.if (!isAlias(beanName)) {try {RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);// Only check bean definition if it is complete.if (!mbd.isAbstract() && (allowEagerInit ||(mbd.hasBeanClass() || !mbd.isLazyInit() || isAllowEagerClassLoading()) &&!requiresEagerInitForType(mbd.getFactoryBeanName()))) {// In case of FactoryBean, match object created by FactoryBean.boolean isFactoryBean = isFactoryBean(beanName, mbd);BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();boolean matchFound =(allowEagerInit || !isFactoryBean ||(dbd != null && !mbd.isLazyInit()) || containsSingleton(beanName)) &&(includeNonSingletons ||(dbd != null ? mbd.isSingleton() : isSingleton(beanName))) &&isTypeMatch(beanName, type);if (!matchFound && isFactoryBean) {// In case of FactoryBean, try to match FactoryBean instance itself next.beanName = FACTORY_BEAN_PREFIX + beanName;matchFound = (includeNonSingletons || mbd.isSingleton()) && isTypeMatch(beanName, type);}if (matchFound) {result.add(beanName);}}}catch (CannotLoadBeanClassException ex) {if (allowEagerInit) {throw ex;}// Probably a class name with a placeholder: let's ignore it for type matching purposes.if (logger.isDebugEnabled()) {logger.debug("Ignoring bean class loading failure for bean '" + beanName + "'", ex);}onSuppressedException(ex);}catch (BeanDefinitionStoreException ex) {if (allowEagerInit) {throw ex;}// Probably some metadata with a placeholder: let's ignore it for type matching purposes.if (logger.isDebugEnabled()) {logger.debug("Ignoring unresolvable metadata in bean definition '" + beanName + "'", ex);}onSuppressedException(ex);}}}// Check manually registered singletons too.for (String beanName : this.manualSingletonNames) {try {// In case of FactoryBean, match object created by FactoryBean.if (isFactoryBean(beanName)) {if ((includeNonSingletons || isSingleton(beanName)) && isTypeMatch(beanName, type)) {result.add(beanName);// Match found for this bean: do not match FactoryBean itself anymore.continue;}// In case of FactoryBean, try to match FactoryBean itself next.beanName = FACTORY_BEAN_PREFIX + beanName;}// Match raw bean instance (might be raw FactoryBean).if (isTypeMatch(beanName, type)) {result.add(beanName);}}catch (NoSuchBeanDefinitionException ex) {// Shouldn't happen - probably a result of circular reference resolution...if (logger.isDebugEnabled()) {logger.debug("Failed to check manually registered singleton with name '" + beanName + "'", ex);}}}return StringUtils.toStringArray(result);}
可能看到这里有的人已经有疑问了,名字一样为什么要调用3次getBeanNamesForType这个方法?其实仔细看就会发现这三个方法的签名不同 ,spring这么做我理解可能是为了更方便传递参数,因为每一次调用都会传递更多的参数进去,其实spring有很多类都是这样的重载方法,然后嵌套多层调用。
然后最最关键的就是这句代码了return new NamedBeanHolder<>(beanName, getBean(beanName, requiredType, args));这句代码中的getBean,才是真正去拿Bean的方法。我们看到先进入了org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String, java.lang.Class<T>, java.lang.Object...)这个方法
public <T> T getBean(String name, @Nullable Class<T> requiredType, @Nullable Object... args)throws BeansException {/*** 这里又是一个空方法*/return doGetBean(name, requiredType, args, false);}
下面这个doGetBean方法的代码比较长,还请大家耐心的看下去
@SuppressWarnings("unchecked")protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {/*** 通过 name 获取 beanName。这里不使用 name 直接作为 beanName 有两个原因* 1、name 可能会以 & 字符开头,表明调用者想获取 FactoryBean 本身,而非 FactoryBean* 实现类所创建的 bean。在 BeanFactory 中,FactoryBean 的实现类和其他的 bean 存储* 方式是一致的,即 <beanName, bean>,beanName 中是没有 & 这个字符的。所以我们需要* 将 name 的首字符 & 移除,这样才能从缓存里取到 FactoryBean 实例。* 2、还是别名的问题,转换需要* &beanName*/final String beanName = transformedBeanName(name);Object bean;// Eagerly check singleton cache for manually registered singletons./*** 这个方法在初始化的时候会调用,在getBean的时候也会调用* 为什么需要这么做呢?* 也就是说spring在初始化的时候先获取这个对象* 判断这个对象是否被实例化好了(普通情况下绝对为空====有一种情况可能不为空)* 从spring的bean容器中获取一个bean,由于spring中bean容器是一个map(singletonObjects)* 所以你可以理解getSingleton(beanName)等于beanMap.get(beanName)* 需要说明的是在初始化时候调用一般都是返回null*/// 先从缓存中获取,因为在容器初始化的时候或者其他地方调用过getBean,已经完成了初始化Object sharedInstance = getSingleton(beanName);// 如果已经初始化过,直接从缓存中获取if (sharedInstance != null && args == null) {//这里的代码是对于日志的记录,方便我们以后阅读应该注释,不影响spring功能
// 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 + "'");
// }
// }/*** 如果 sharedInstance 是普通的单例 bean,下面的方法会直接返回。但如果* sharedInstance 是 FactoryBean 类型的,则需调用 getObject 工厂方法获取真正的* bean 实例。如果用户想获取 FactoryBean 本身,这里也不会做特别的处理,直接返回* 即可。毕竟 FactoryBean 的实现类本身也是一种 bean,只不过具有一点特殊的功能而已。*/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)) {throw new BeanCurrentlyInCreationException(beanName);}// Check if bean definition exists in this factory.BeanFactory parentBeanFactory = getParentBeanFactory();if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {// Not found -> check parent.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.return (T) parentBeanFactory.getBean(nameToLookup, args);}else {// No args -> delegate to standard getBean method.return parentBeanFactory.getBean(nameToLookup, requiredType);}}if (!typeCheckOnly) {//添加到alreadyCreated set集合当中,表示他已经创建过一次markBeanAsCreated(beanName);}try {final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);checkMergedBeanDefinition(mbd, beanName, args);//检查是否有depends on// Guarantee initialization of beans that the current bean depends on.String[] dependsOn = mbd.getDependsOn();if (dependsOn != null) {for (String dep : dependsOn) {if (isDependent(beanName, dep)) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");}registerDependentBean(dep, beanName);try {getBean(dep);}catch (NoSuchBeanDefinitionException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"'" + beanName + "' depends on missing bean '" + dep + "'", ex);}}}//创建bean实例// Create bean instance.if (mbd.isSingleton()) {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;}});bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);}else if (mbd.isPrototype()) {// It's a prototype -> create a new instance.Object prototypeInstance = null;try {beforePrototypeCreation(beanName);prototypeInstance = createBean(beanName, mbd, args);}finally {afterPrototypeCreation(beanName);}bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);}else {String scopeName = mbd.getScope();final Scope scope = this.scopes.get(scopeName);if (scope == null) {throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");}try {Object scopedInstance = scope.get(beanName, () -> {beforePrototypeCreation(beanName);try {return createBean(beanName, mbd, args);}finally {afterPrototypeCreation(beanName);}});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.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的过程了,首先是从缓存中拿,因为doGetBean有很多地方会调用,可能当前调用的时候缓存里已经有bean存在了。缓存中拿bean的真正方法是org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, boolean)
@Nullableprotected Object getSingleton(String beanName, boolean allowEarlyReference) {//从map中获取bean如果不为空直接返回,不再进行初始化工作//一个程序员提供的对象这里一般都是为空的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);}}}}return singletonObject;}
总结
为了控制文章的篇幅,下面的代码我会放到第二部分去讲,谢谢大家关注














