根据之前的分析,可以知道我们已经把配置文件的元素解析好了,并且把bean标签对应的元素都解析到了beanDefinition的对应属性中.下面就先大致看下bean加载的整个流程,细节后面再分析
Cat whiteCat =(Cat) bf.getBean("whiteCat");
上面的getBean到底实现了哪些功能,一起 看看源码吧.
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
// 得到name对应的真实beanname,因为有时候参数传的可能不是真的beanName
String beanName = transformedBeanName(name);
Object beanInstance;
// 从缓存中获取bean或bean工厂
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
// 返回对应的实例,有时候存在诸如beanFactory的情况并不是直接返回实例本身而是返回指定方法返回的实例
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
if (isPrototypeCurrentlyInCreation(beanName)) {
// 说明prototype类型的beanName已经在创建中了,表明有循环依赖
// Spring只尝试解决单例bean的循环依赖
// 所以这里会抛出异常
throw new BeanCurrentlyInCreationException(beanName);
}
// 如果beanDefinitionMap中也就是在所有的已经加载的类中不包含beanName,则尝试从parentBeanFactory中寻找
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
String nameToLookup = originalBeanName(name);
// 递归到beanFactory里边去找
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
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);
}
}
// 如果不是仅仅做类型检查则是创建bean,这里咬进行记录
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
.tag("beanName", name);
try {
if (requiredType != null) {
beanCreation.tag("beanType", requiredType::toString);
}
// 将存储XML配置文件的GenericBeanDefinition转换为RootBeanDefinition
// 如果指定BeanName是子Bean的话同时会合并父类的相关属性
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 得到标签解析的depend-on元素的值
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
// 存在依赖,需要递归实例化依赖的bean
for (String dep : dependsOn) {
// 这里是会有一个map记录每次依赖的关系,如果存在循环依赖直接抛出异常
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);
}
}
}
// 实例化mbd.
// singleton模式的创建
if (mbd.isSingleton()) {
// 注意传递的参数:beanName和一个ObjectFactory
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);
}
// prototype类型的
else if (mbd.isPrototype()) {
Object prototypeInstance = null;
try {
// 创建之前会把当前beanName加入到创建池中,用来记录开始创建的状态
beforePrototypeCreation(beanName);
// 创建bean的方法
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
// 创建完成,把beanName从创建池中移除
afterPrototypeCreation(beanName);
}
// 同上
beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
// scope除了上面两种还有其他的比如request等
else {
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 {
Object 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();
}
}
// 适应bean实例,把bean实例转换成requiredType的类型
return adaptBeanInstance(name, beanInstance, requiredType);
}
@SuppressWarnings("unchecked")
<T> T adaptBeanInstance(String name, Object bean, @Nullable Class<?> requiredType) {
// Check if required type matches the type of the actual bean instance.
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
// 看看需不需要做类型转换
Object convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return (T) convertedBean;
}
catch (TypeMismatchException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
总结一下getBean里边做了什么?
1、先把传递过来的参数转成真正的beanName,因为可能传递的是别名、或者带&的工厂名
2、先从缓存中获取bean,注意这里边有一个三级缓存.如果缓存不为空的话,因为可能是ObjectFactory类型,所以还需要从这个类型中调用真正的方法来获取真正的bean
3、如果缓存为空,先进行了判断,如果是prototype类型并且正在创建的话,说明发生了循环依赖,Spring只尝试解决单例模式的循环依赖,所以会直接抛出异常.
4、如果beanDefinitionMap中没有对应的则从parentBeanFactory里边寻找,然后再分情况递归调用,创建对应的bean
5、将存储XML配置文件的GenericBeanDefinition转换为RootBeanDefinition,如果指定BeanName是子Bean的话同时会合并父类的相关属性,比如父类的scope属性等
6、检查bean元素的depend-on的解析结果,如果有依赖,则先递归实例化依赖,并且在循环所有依赖的时候会把他用一个map记录依赖关系,key是被依赖的bean,value师当前bean,这样既可以记录关系,又可以检查是不是存在循环依赖.
7、根据不同的scope的值创建实例.
8、把bean转换成requiredType指定的类型.