Bean加载过程
概述
本系列将开始探究Spring源码,也是自己对Sping学习的一个过程,这章从Spring的Bean加载
过程开始。
创建测试模块
下源码过程不再赘述,在源码中新建一个测试模块,在gradle依赖中加入
compile(project(":spring-context"))
项目架构如下图
测试类
@Test
public void testSimpleLoad(){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
Car car = (Car) context.getBean("car");
System.out.println("car = " + car);
}
配置类
@Configuration
@ComponentScan(basePackages = {"com.yy.config"})
public class MainConfig {
@Bean
public Car car(){
Car car = new Car();
car.setCarName("Benz");
car.setPrice(1111);
return car;
}
}
启动后断点调试,进入doGetBean
方法
@SuppressWarnings("unchecked")
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException{
/**
*提取对应的beanName
* 这里传入的参数可能是别名,也可能是FactoryBean
*/
final String beanName = transformedBeanName(name);
Object bean;
/**
* 检查缓存中或者实例工厂中是否有对应的实例
* 创建依赖的时候为了避免循环依赖,
* spring创建bean的原则是不等bean创建完成就将创建bean的ObjectFactory提早曝光
* 将ObjectFactory加入到缓存中,一旦下个bean创建时需要依赖某个bean则直接从ObjectFactory中取
*/
//直接尝试从缓存获取或者singletonFactories中的ObjectFactory中取
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
//返回对应的实例,有时候存在诸如beanFactory的情况并不是直接返回实例本身,而是返回指定方法返回的实例
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();
// 如果beandefinitionMap中也就是在所有已经加载的类中不包括beanName则尝试从parentBeanFactory中获取
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) {
//递归到BeanFactory中寻找
// Delegation to parent with explicit args.
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);
}
try {
/**
*将存储XML配置文件的GernericBeanDefinition转换成RootBeanDefinition
* 如果自顶beanName是子Bean的话同时会合并父类的相关属性
*/
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
String[] dependsOn = mbd.getDependsOn();
/**
* 若存在依赖则需要递归实例化依赖的bean
*/
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后,就开始实例化RootBeanDefinition对象
//singleton模式的创建
// 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;
}
});
//prototype模式的创建(new)
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 {
//指定的scope上实例bean
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;
}
}
//检查需要的类型是否符合bean的实际类型
// 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.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;
}
简要概述一下bean加载过程
bean加载过程
1.转换对应beanName
final String beanName = transformedBeanName(name);
此处传入的参数name其实并不一定是beanName,可能是别名,也可能是FactoryBean,所以需要一系列解析,解析包括
去除FactoryBean修饰符,也就是如果name="&aa" ,那么会首先去除&而使name=“aa”
取指定alias锁标识的最终beanName
2.尝试从缓存中加载单例
单例在Spring的同一个容器中只会被创建一次,后续再获取bean,就直接从单例缓存中获取了。
当然这里也只是尝试加载,首先尝试从缓存中加载,如果加载不成功则再次尝试从singletonFactories中加载。
因为在创建单例bean的时候会有历来注入的情况,为了避免循环依赖,spring创建bean原则是不等bean创建完成就会将
创建的ObjectFactory提早曝光到缓存中,一旦下一个bean创建的时候需要依赖上一个bean则直接从使用ObjectFactory
3.bean的实例化
如果从缓存中得到了原始bean,则需要对bean进行实例化。这里强调一下,缓存中记录的只是最原始的bean状态,并不一定
是我们最终想要的bean。
4.原型模式的依赖检查
只有在单例情况下才会尝试解决循环依赖,也就是下面这个方法
isPrototypeCurrentlyInCreation(beanName)