spring单例bean的创建

设计

假设我们自己来设计怎么去创建bean,有几种方案可以提供

  1. 每次需要的时候new一个对象(这个也是我们常用的)
  2. 对第一个进行升级,把new对象的工作交给工厂
  3. 假设我们的对象是稳定的,而且是线程安全的,那么我们可以使用同一个对象,可以把这个对象缓存起来。放到一个容器,每次需要用的时候拿出来

spring做的事情就是帮我们创建对象,并且把对象缓存到一个Map容器中,需要的时候从容器获取即可。

上图

spring单例bean的创建

关键的前置条件

在bean创建之前有些工作时必须完成的,它们是创建bean的必要条件

  1. BeanDefinition的收集已经完成(需要创建那些bean)
  2. 工厂初始化完成(容器的准备)
  3. 配置加载完成(bean中属性的注入)
    。。。

步骤

  • 循环所有的beanName,对每个beanName进行创建
.........省略
// Trigger initialization of all non-lazy singleton beans...
		for (String beanName : beanNames) {
					....
					// getBean就是创建对象操作
					getBean(beanName);
					....
				
			}
		}
.........
  • 先从缓存中拿取实例,如果缓存中有,直接返回,如果缓存中没有,创建对象
protected <T> T doGetBean(
			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException {

		.........
		// 从缓存中拿取实例
		Object sharedInstance = getSingleton(beanName);
		.........
		// 重点看这里,大部分情况都是单例
			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;
					}
				});
				// factoryBean 的getObject 方法获取的实例 走这里
				bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
			}
		.........
			
  • 最终使用java的反射api来创建对象
....
// 实例化对象
return ctor.newInstance(argsWithDefaultValues);
...
  • 创建对象完成之后放入缓存
....
		if (newSingleton) {
			// 放入缓存
			addSingleton(beanName, singletonObject);
		}
		...		
  • 上述主要讲了spring对象单例的创建
上一篇:Spring-bean的循环依赖以及解决方式


下一篇:AOP收集信息