spring源码解读之getBean方法(一)
前言大家使用spring,最常接触到的就是bean,大家也知道spring中用一句getBean就能取出一个实例化好的bean,这个bean是属于IOC容器管理的,那么大家有没有看过getBean方法的源码呢,知不知道spring容器到底是怎么得到一个实例化好的bean的呢,这一次,我和大家一起来研究getBean方法的源码开始首先我来一段非常简单的代码//我是用注解方式配置的a...
前言
大家使用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这个类上,所以就不展开研究这个类了,我们接下去看
@Override
public <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方法得到这个holder
NamedBeanHolder<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.
*/
@Override
public 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")
@Nullable
private <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);这句代码,这个方法进去之后其实会调用很多层
@Override
public String[] getBeanNamesForType(@Nullable Class<?> type) {
return getBeanNamesForType(type, true, true);
}
@Override
public 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去获取所有的BeanFactoryProcessor
private 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)
@Nullable
protected 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;
}
总结
为了控制文章的篇幅,下面的代码我会放到第二部分去讲,谢谢大家关注
更多推荐
所有评论(0)