Spring之Bean

入口

  • SpringBoot启动过程一文中,提到在refresh过程里,会通过扫描解析已注入的@Configuration类的@ComponentScan@Import@Component@Bean…注册其余的BeanDefinition;
  • springmvc通过web.xmlcontextConfigLocation的值,加载并解析beans文件;
  • 自己创建ClassPathXmlApplicationContext,指定configLocation,在refresh时,解析config文件注册BeanDefinition;

初始化

我们的容器在refresh通过配置载入约定的BeanDefinition,并在之后预先初始化一部分Non-Lazy的bean。接下来我们来看下一个bean是如何初始化的,这里会涉及到面试最常见的三级缓存以及bean的生命周期

一个bean的载入是通过getBean开始的,如果已在容器里,就直接返回已创建的对象,如果没有就先创建这个bean,再返回。
我们直接从AbstractBeanFactory#doGetBean开始, 这个方法比较长,先忽略部分代码,我们从一个bean的从无到有过程分析:

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
    protected <T> T doGetBean(
			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException {

		String beanName = transformedBeanName(name);
		Object bean;

		// Eagerly check singleton cache for manually registered singletons.
		Object sharedInstance = getSingleton(beanName);
		// 如果已存在实例,返回
		if (sharedInstance != null && args == null) {
			...
			// 考虑到该bean可能是个FactoryBean,需要获取真正的bean对象
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		} else {
		    // 一些校验,以及是否从parentBeanFactory里获取该bean的判断
			...
			try {
				RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);

				// 获取bean的依赖 `@DependsOn`
				// 最终还是通过getBean获取依赖的bean
				String[] dependsOn = mbd.getDependsOn();
				if (dependsOn != null) {
					for (String dep : dependsOn) {
						...
					}
				}

				// 如果当前bean是Singleton
				if (mbd.isSingleton()) {
				    // 第二个参数是匿名FactoryBean,实现其`getObject`方法
					sharedInstance = getSingleton(beanName, () -> {
						try {
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
						    // 销毁bean
							destroySingleton(beanName);
							throw ex;
						}
					});
					// 获取给定bean实例的对象
					// 如果是FactoryBean,则获取bean实例本身或其创建的对象 
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}

				else if (mbd.isPrototype()) {
					...
				}

				else {
					...
			}
			catch (BeansException ex) {
				cleanupAfterBeanCreationFailure(beanName);
				throw ex;
			}
		}

		// 类型转换
		if (requiredType != null && !requiredType.isInstance(bean)) {
			...
		}
		return (T) bean;
	}
}

getInstance

DefaultSingletonBeanRegistrygetInstance有3个重载,就上面的doGetBean方法用到了2个重载:第一次getInstance是只从容器里取(这里可以看到Spring bean的三级缓存);第二次getInstance是先从容器里获取,如果没有的话就创建:

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {

    @Override
	@Nullable
	public Object getSingleton(String beanName) {
		return getSingleton(beanName, true);
	}

	
	@Nullable
	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
	    // singletonObjects里存放的是最终实例完毕的bean
		Object singletonObject = this.singletonObjects.get(beanName);
		// 一级缓存没有并且不在创建中(即未开始创建流程)
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			synchronized (this.singletonObjects) {
			    // 从二级缓存获取对象
				singletonObject = this.earlySingletonObjects.get(beanName);
				// 如果不在二级缓存,就从三级缓存(存放ObjectFactory)
				if (singletonObject == null && allowEarlyReference) {
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					// 如果在三级缓存里,通过`getObject`方法获取实例
					// 并放入二级缓存里
					// 此时该实例并未`初始化`完毕
					if (singletonFactory != null) {
						singletonObject = singletonFactory.getObject();
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}

    public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(beanName, "Bean name must not be null");
		// 同步执行
		synchronized (this.singletonObjects) {
			Object singletonObject = this.singletonObjects.get(beanName);
			if (singletonObject == null) {
				if (this.singletonsCurrentlyInDestruction) {
					throw new BeanCreationNotAllowedException(beanName,
							"Singleton bean creation not allowed while singletons of this factory are in destruction " +
							"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
				}
				...
				// 将beanName添加到singletonsCurrentlyInCreation集合中
				beforeSingletonCreation(beanName);
				boolean newSingleton = false;
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = new LinkedHashSet<>();
				}
				try {
				    // 获取对象,执行`createBean`方法
					singletonObject = singletonFactory.getObject();
					newSingleton = true;
				}
				catch (IllegalStateException ex) {
					...
				}
				catch (BeanCreationException ex) {
					...
				}
				finally {
					if (recordSuppressedExceptions) {
						this.suppressedExceptions = null;
					}
					// 将beanName从singletonsCurrentlyInCreation集合中移除
					afterSingletonCreation(beanName);
				}
				if (newSingleton) {
				    // 将singletonObject放入singletonObjects map中
				    // 并将其从singletonFactories(三级缓存),从earlySingletonObjects(二级缓存)删除
					addSingleton(beanName, singletonObject);
				}
			}
			return singletonObject;
		}
	}
}

createBean

singletonFactorygetObject方法将调用到createBean

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
		implements AutowireCapableBeanFactory {
	@Override
	protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {

		RootBeanDefinition mbdToUse = mbd;

		Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
		if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
			mbdToUse = new RootBeanDefinition(mbd);
			mbdToUse.setBeanClass(resolvedClass);
		}
		try {
		    // 方法替换 比如init-method/replace-method
			mbdToUse.prepareMethodOverrides();
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
					beanName, "Validation of method overrides failed", ex);
		}

		try {
			// 实例前处理
			// 会依次调用InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法
			// 再调用它的postProcessAfterInitialization方法
			// 这两个方法是不是感觉哪里看过,再AOP就是通过这两个方法生成的代理类
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			if (bean != null) {
				return bean;
			}
		}
		catch (Throwable ex) {
			throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
					"BeanPostProcessor before instantiation of bean failed", ex);
		}

		try {
		    // 创建bean
		    // 下文对`doCreateBean`详细解析
			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
			...
			return beanInstance;
		}
		catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
			throw ex;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
		}
	}
	
	protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {

		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
		·   // 创建实例
		    // 使用实例化的策略:工厂方法、构造器自动装配、简单实例化
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		Object bean = instanceWrapper.getWrappedInstance();
		Class<?> beanType = instanceWrapper.getWrappedClass();
		if (beanType != NullBean.class) {
			mbd.resolvedTargetType = beanType;
		}
		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				try {
				    // 调到所有的实现了MergedBeanDefinitionPostProcessor接口的实例
				    // 其中有个非常关键的类:AutowiredAnnotationBeanPostProcessor
				    // 该类会扫描到正在实例化的bean的类里面属性和方法上面的`@Autowired`、`@Value`和`@Inject`注解
				    // 然后把对应的方法或者属性封装起来,最终封装成InjectionMetadata对象。
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				}
				mbd.postProcessed = true;
			}
		}

		// 提早暴露实例,以便能正确处理循环依赖的情况
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			...
			// 将beanName及匿名singletonFactory放入`singletonFactories`(三级缓存)
			// 将beanName从earlySingletonObjects移除(二级缓存)
			// 将beanName添加到registeredSingletons集合中
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// 开始初始化bean
		Object exposedObject = bean;
		try {
		    // 填充bean的属性
			populateBean(beanName, mbd, instanceWrapper);
			// 初始化:依次执行以及bean post processor里的postProcessBeforeInitialization、init-method以及postProcessAfterInitialization
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		catch (Throwable ex) {
			// 异常处理
			...
		}

		if (earlySingletonExposure) {
		    // 此时的bean并未放入singletonObjects集合中,所以取出来的earlySingletonReference为null
			Object earlySingletonReference = getSingleton(beanName, false);
			if (earlySingletonReference != null) {
				...
			}
		}

		try {
		    // 给当前bean注册一个DisposableBean接口(DisposableBeanAdapter)
		    // 包括`DestructionAwareBeanPostProcessors`、DisposableBean 接口以及自定义的`destroy-method`
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
		}

		return exposedObject;
	}
}

循环依赖

我们看下下面这个例子:

@Component("beanA")
class A {
    @Autowired
    B b;
}

@Component("beanB")
class B {
    @Autowired
    A a;
}

从这个例子我们看到beanA依赖了beanB,而beanB又依赖于beanA。这就是我们说的循环依赖。

我们先简单想象下这两个单例bean的创建过程:当我们实例化beanA后,在设置它的属性时发现需要beanB; 于是我们就去创建beanB,实例化beanB后,在设置其属性时,发现它又需要一个class A实例;因为此时beanA尚未初始化完毕,所以还未加到容器里,于是又会去创建一个class A的实例,实例化完毕后,设置属性时发现需要一个class B实例… 如此反复,A需要B,B又需要A,这就形成了循环依赖。

那么Spring是如何解决这个问题的呢?查看上文的源码,其实已经有答案了:引入了缓存。简单得理解:当beanA实例化完成后,就加入一个缓存中,再进行初始化;当beanB需要class A时,先从缓存中取,缓存中没有的话再去重新实例化;当beanA初始化完成后再放入容器里,并删除缓存。

当然在Spring中没有那么简单粗暴,要更加完善些:Spring引入了三级缓存;

  • 一级:singletonObjects,单例对象的缓存-从bean名到bean实例;
  • 二级:earlySingletonObjects,缓存早期单例对象(未初始化完毕)-从bean名到bean实例;
  • 三级:singletonFactories,缓存单例工厂-bean名到ObjectFactory;

我们直接看缓存的使用吧:

三级缓存过程

小结

我们定义的bean一开始是以BeanDefinition的形式存放在BeanFactory里,当我们通过getBean方法向容器获取指定bean的时候,该bean才会开始实例化以及初始化;

在实例化过程中,会先依次调用InstantiationAwareBeanPostProcessorpostProcessBeforeInstantiationpostProcessAfterInitialization方法,方便我们对bean的属性做一些改变,比如AOP就利用了对这两个方法对bean进行了代理;如果没有产生合适的bean, 再选择合适的实例化方式进行实例化:工厂方法、构造器自动装配、简单实例化;

接着开始初始化:先解析bean类里的@Autowired@Value@Inject注解,并保存起来;接着利用提早暴露实例化好的beansingletonFactories(三级缓存),解决循环依赖问题;再接着开始初始化该bean,包括填充属性以及执行一些初始化方法;再接着按需给该bean注册一个DisposableBean接口,在该bean在销毁的时候执行一些特定的逻辑。

然后将完整的bean放入BeanFactorysingletonObjects中,并将其从singletonFactories(三级缓存)和earlySingletonObjects(二级缓存)删除。

以上小结只是加载bean的一种路径,因为加载bean时有很多判断、递归,这里就不赘述了。

以上小结中,有两点比较重要的点:1. bean的生命周期;2. 循环依赖的解决;循环依赖的流程图上文已给出,这里总结下bean的生命周期

bean

bean的生命周期

作用域

在使用Spring Bean过程中,我们会接触到作用域这个概念,常见的Scope:

  1. Prototype: 原型,每次获取都会产生新的实例;
  2. Singleton: 单例,在应用的生命周期里唯一;
  3. Request: Web应用专属,在一个请求里唯一;
  4. Session: Web应用专属,在一个会话里唯一;

这里有一个比较有意思的问题:当一个Prototype beanA跟一个Singleton beanB绑定后,我们在beanB里多次获取beanA是同一个对象还是不通的对象?

当然是同一个啦,因为单例是固定的,那它里面的属性都是不会变的。那我们在Spring里使用原型模式是不是要很小心,因为你以为的每次使用都是新对象,其实都是老对象,然后数据可能会因此出错?其实不然,Spring考虑到这点了,并使用了TargetSource替我们解决这个问题。

public class TestController {
    @Autowired
    ResponseData testBean;

    @GetMapping("test")
    public ResponseData test() {
        return testBean;
    }

    @Bean
    @Scope(scopeName = ConfigurableBeanFactory.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.TARGET_CLASS)
    public ResponseData testBean() {
        return ResponseData.success("hello");
    }
}

在这里插入图片描述
从上图我们可以得出结论,testBean是一个通过CGLIB动态代理的实例, 在intercept方法里通过targetSource.getTarget();获取到真正的bean

public class SimpleBeanTargetSource extends AbstractBeanFactoryBasedTargetSource {

	@Override
	public Object getTarget() throws Exception {
		return getBeanFactory().getBean(getTargetBeanName());
	}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值