Bean的加载过程分析
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
Students s = (Students) ctx.getBean("stu2");
追踪源码到 AbstractBeanFactory
中 doGetBean
方法:
(把源码贴出来,在源码中加上了注释)
内部调用 doGetBean() 方法,其接受四个参数:
- name:要获取 bean 的名字
- requiredType:要获取 bean 的类型
- args:创建 bean 时传递的参数。这个参数仅限于创建 bean 时使用
- typeCheckOnly:是否为类型检查
@SuppressWarnings("unchecked")
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
// 转换BeanName,根据 name 获取真正的 beanName 或 FactroyBean 的 name
final String beanName = transformedBeanName(name);
Object bean;
// 从缓存中或者实例工厂中获取 bean
// 这里会涉及到解决循环依赖 bean 的问题
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
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 + "'");
}
}
// 从缓存中取到了Bean,再进一步做实例化处理
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// 只解决单例模式下循环依赖的问题,
// 判断是不是原型模式下的bean,如果是的话,则抛出异常
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 从父类容器中加载bean
// 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 (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);
}
}
// // 如果不是仅仅做类型检查则是创建bean,这里需要记录
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
// 从容器中获取 beanName 相应的 GenericBeanDefinition,并将其转换为 RootBeanDefinition
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// 检查给定的合并的 BeanDefinition
checkMergedBeanDefinition(mbd, beanName, args);
// 处理所依赖的 bean
// Guarantee initialization of beans that the current bean depends on.
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dependsOnBean : dependsOn) {
// 如果dependsOnBean已经注册为了beanName的依赖bean,则抛出异常
if (isDependent(beanName, dependsOnBean)) {
throw new BeanCreationException("Circular depends-on relationship between '" +
beanName + "' and '" + dependsOnBean + "'");
}
// 注册依赖的bean
registerDependentBean(dependsOnBean, beanName);
// 递归getBean方法获取bean
getBean(dependsOnBean);
}
}
// 单例模式,bean的实例化
// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
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);
}
// 原型模式,bean的实例化
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);
}
// 从指定的 scope 下创建 bean
else {
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
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;
}
}
// // 检查需要的类型是否符合 bean 的实际类型
// Check if required type matches the type of the actual bean instance.
if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
try {
return getTypeConverter().convertIfNecessary(bean, requiredType);
}
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;
}
梳理为以下步骤:
- 获取beanName ,代码如下:
final String beanName = transformedBeanName(name);
protected String transformedBeanName(String name) {
return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}
public static String transformedBeanName(String name) {
Assert.notNull(name, "'name' must not be null");
String beanName = name;
// 去除beanFactory的修饰符,如果 beanName 是以 & 开头的,则截取掉 &
while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
}
return beanName;
}
// 转换别名
public String canonicalName(String name) {
String canonicalName = name;
// Handle aliasing...
String resolvedName;
do {
// 根据别名取到真正的beanName
resolvedName = this.aliasMap.get(canonicalName);
if (resolvedName != null) {
canonicalName = resolvedName;
}
}
while (resolvedName != null);
return canonicalName;
}
- 从单例 bean 缓存中获取 bean 对应代码段如下:
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
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 + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
单例模式的 Bean 在 Bean 的整个生命周期当中只创建一次,第一次创建后将将Bean 加载到缓存当中,以后加载 Bean 时就都从单例缓存里取。 如果从缓存中得到了 Bean ,就调用 getObjectForBeanInstance()
方法,对Bean 进行实例化处理,因为缓存中记录的是最原始的 bean 状态,我们得到的不一定是我们最终想要的 bean。
如果没有从缓存中获取到Bean,则到了下边的逻辑:
3. 原型模式依赖检查与 parentBeanFactory 对应代码段
// spring 只解决单例模式下的循环依赖问题,对于原型模式的话直接抛出异常
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 获取 parentBeanFactory来加载Bean
// Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
// 如果parentBeanFactory 不为空,且 该Bean没有注册 BeanDefinition缓存中,则使用 parentBeanFactory 加载 Bean
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
// 获取原始的 BeanName
String nameToLookup = originalBeanName(name);
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);
}
}
如果容器缓存中没有相对应的 BeanDefinition 则会尝试从父类工厂(parentBeanFactory)中加载,然后再去递归调用 getBean()。
- 类型检查
// 如果不是类型检查,则要记录bean的创建
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
- RootBeanDefinition 处理:
try {
// 将存储在 XML配置文件中的GemericBeanDefinition 转换为 RootBeanDefinition
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
- 依赖处理:
// Guarantee initialization of beans that the current bean depends on.
String[] dependsOn = mbd.getDependsOn();
// 存在依赖
if (dependsOn != null) {
for (String dependsOnBean : dependsOn) {
if (isDependent(beanName, dependsOnBean)) {
throw new BeanCreationException("Circular depends-on relationship between '" +
beanName + "' and '" + dependsOnBean + "'");
}
//注册依赖关系
registerDependentBean(dependsOnBean, beanName);
getBean(dependsOnBean);
}
}
因为 bean 的初始化过程中很坑用到某些属性,而某些属性很可能是动态配置的,并且配置成依赖于其他bean,那么这个时候就有必要先加载依赖的bean 。所以, 在Spring的加载过程中,在初始化某一个bean的时候首先会初始化这个bean 所对应的依赖。
- 根据bean的作用域对bean实例化
// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
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 '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
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;
}
registerDependentBean(dependsOnBean, beanName)
注册依赖关系
比如,加载 A 的时候,发现A依赖B ,在下边标注一下方面区分
- beanName : 所依赖的beanName (B)
- dependentBeanName 当前要加载的 beanName (A)
/**
* Register a dependent bean for the given bean,
* to be destroyed before the given bean is destroyed.
* @param beanName the name of the bean
* @param dependentBeanName the name of the dependent bean
*/
public void registerDependentBean(String beanName, String dependentBeanName) {
String canonicalName = canonicalName(beanName);
synchronized (this.dependentBeanMap) {
Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
//
if (dependentBeans == null) {
dependentBeans = new LinkedHashSet<String>(8);
// (bean 的依赖关系:dependentBeans 依赖 canonicalName)
// 依赖我的
this.dependentBeanMap.put(canonicalName, dependentBeans);
}
dependentBeans.add(dependentBeanName);
}
synchronized (this.dependenciesForBeanMap) {
Set<String> dependenciesForBean = this.dependenciesForBeanMap.get(dependentBeanName);
if (dependenciesForBean == null) {
dependenciesForBean = new LinkedHashSet<String>(8);
// 我依赖的
this.dependenciesForBeanMap.put(dependentBeanName, dependenciesForBean);
}
dependenciesForBean.add(canonicalName);
}
}
总结Bean的加载过程:
- 分析从缓存中获取单例 bean,以及对 bean 的实例中获取对象
- 如果从单例缓存中获取 bean,Spring 是怎么加载的呢?所以第二部分是分析 bean 加载,以及 bean 的依赖处理
- bean 已经加载了,依赖也处理完毕了,第三部分则分析各个作用域的 bean 初始化过程。