002-Spring Bean 从扫描到创建

Spring Bean 从扫描到创建

扫描流程 class 到 BeanDefinition

引入

上一个分析文章中我们知道从Class到一个Bean中间是需要把Class先创建成BeanDefinition
然后由Spring控制在不同的时机用不用的方法依据BeanDefinition转化为Bean供我们使用

那么Class到BeanDefinition的流程是什么?
先说结论这个过程主要发生在
ClassPathBeanDefinitionScanner : 扫描读取Class文件为Resource对象

扫描:ClassPathBeanDefinitionScanner

org.springframework.context.annotation.ClassPathBeanDefinitionScanner#doScan
这个方法就是扫描包中的文件,把文件加载成Resource对象的并注册成为BeanDefinition的

doScan

分析下细节:

遍历basePackages : basePackage {
	查找到所有符合要求的BeanDefinition(findCandidateComponents(basePackage)) : candidates
	遍历所有的 BeanDefinitions : beanDefinitions {
		解析:Scope.class
		获取beanName
		if instanceof AbstractBeanDefinition : 执行postProcessBeanDefinition:
			1. 设置默认值
				setLazyInit
				setAutowireMode(defaults.getAutowireMode());
				setDependencyCheck(defaults.getDependencyCheck());
				setInitMethodName(defaults.getInitMethodName());
				setEnforceInitMethod(false);
				setDestroyMethodName(defaults.getDestroyMethodName());
				setEnforceDestroyMethod(false);
			2. setAutowireCandidate
		if instanceof AnnotatedBeanDefinition : 解析 @Lazy@Primary@DependsOn@Role@Description
		if (this.registry是否存在beanName) {
			注册BeanDefinitionthis.registry
		}
	}
}

findCandidateComponents(basePackage)

if 没有 编写索引文件 那么进入 scanCandidateComponents(basePackage); 

scanCandidateComponents(basePackage) {
	路径转化 包名转化为三部分组成的路径
		1. classpath*:
		2. 包名中的 "." 替换为 "/"
		3. /**/*.class
	扫描路径中的class文件为 Resource[] resources
	遍历 resources :: resource {
		判断是否符合条件
			1. excludeFilters 符合任意一个则排除(默认为空)
			2. includeFilters 符合任意一个则包含(默认registerDefaultFilters()3. 如果命中include 继续检查是否使用@Conditional
		if (没排除,且包含) {
			组装ScannedGenericBeanDefinition sbd
				1. this.beanClass = beanClassName;
				2. this.resource = resource;
				3. this.source = source;
			判断是否可以创建Bean
				1. 非内部类的Class
				2. &&(是具体类 || 是抽象类但是方法上有@Lookupif (判断通过) {
				添加到候选池中 candidates
			}
		}
	}
}

在这里插入图片描述

registerDefaultFilters()

org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#registerDefaultFilters
添加了三个includeFilter

  1. org.springframework.stereotype.Component
  2. javax.annotation.ManagedBean
  3. javax.inject.Named

this.registry

这里的 registry 并不是 AnnotationConfigApplicationContext 虽然 AppContext本身也是Registry
但是这里的 registry 是
org.springframework.context.annotation.ComponentScanAnnotationParser#parse 中 new 出来的
ClassPathBeanDefinitionScanner 中带有的 org.springframework.beans.factory.support.DefaultListableBeanFactory
而在 DefaultListableBeanFactory 维护了一个 Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap(256);

  • 是否存在 : this.beanDefinitionMap.containsKey(beanName);
  • 注册:this.beanDefinitionMap.put(beanName, beanDefinition);

创建流程 BeanDefinition 到 Bean

统一 BeanDefinition 类型

finishBeanFactoryInitialization(beanFactory);

统一为:RootBeanDefinition

创建非懒加载单例bean
扫描所有的BeanDefinition创建Bean在:
org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons

遍历beanDefinitionNames : beanNames : beanName {
	根据beanName 组装 和合并BenaDefinition(RootBeanDefinition) : bd
	//注意这里判断的是是不是抽象的BeanDefinition 而不是判断的是不是一个抽象类
	//抽象的BeanDefinition 在自定义BeanDefinition的时候可以提供一个些公共的属性
	if (bd 不是抽象的 && 是单例的 && 是懒加载的) {
		if (是工厂Bean(FactoryBean)) {
			//这里已经创建一个beanName的Bean了 创建的对象是Class对应的对象
			//也就是说在容器创建的是否并没有创建getObject指定的对象
			//getObject指定的对象是在使用的时候创建的
			Object bean = getBean(FACTORY_BEAN_PREFIX(&) + beanName);
		} else {
			//这里就会真的去创建Bean了
			getBean(beanName);
		}
	}
}

重新遍历 beanNames : beanName {
	根据beanName 获取对象
	if (instanceof SmartInitializingSingleton) 则执行 
		smartSingleton.afterSingletonsInstantiated(); 
		smartInitialize.end();
}
//这里算是生命周期扩展的一个补充 在所有非懒加载单例Bean初始化后执行的2个方法
getMergedLocalBeanDefinition(beanName)

根据beanName组装合并BenaDefinition(RootBeanDefinition)
最终执行逻辑的是:
org.springframework.beans.factory.support.AbstractBeanFactory#getMergedBeanDefinition(java.lang.String, org.springframework.beans.factory.config.BeanDefinition, org.springframework.beans.factory.config.BeanDefinition)

缓存池中获取mbd = this.mergedBeanDefinitions.get(beanName);
if (mbd == null) {
	if (bd.getParentName() == null 且 不是 RootBeanDefinition) {
		mbd = 就根据现有的BeanDefinition创建RootBeanDefinition
	}
	if (bd.getParentName() != null) {
		mbd = 就把父子融合创建RootBeanDefinition
			1. 根据父BeanDefinition创建RootBeanDefinition
			2. 在根据子类BeanDefinition覆盖对应的信息
	}
}
//所以在Spring中常用的是融合后的RootBeanDefinition池子
//这里也起到归类的作用
//比如扫描出来的BeanDefinition是ScannedGenericBeanDefinition
//而根据配置类创建出来的是AnnotatedGenericBeanDefinition
//最终都在这里转化为RootBeanDefinition供创建Bean使用

创建Bean

doGetBean

分析的代码为:
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean

转化BeanNametransformedBeanName(name): beanName
//查看缓存中是否已经有beanName对应的实例了
Object sharedInstance = getSingleton(beanName);
//getObjectForBeanInstance 注释说了可以返回本身 或者 返回FactoryBean 时创建的对象
if (sharedInstance  != null ) {beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);}
if (sharedInstance  == null ) {
	if (curVal = this.prototypesCurrentlyInCreation.get() 且 curVal等于或者包含 beanName) { 认为循环依赖,报错}
	获取父Bean工厂:parentBeanFactory
	if (parentBeanFactory != null 且 自身没有对应的BeanDefinition){
		//这里把beanName 恢复了一下 这个name是之前没有处理前的name,有可能带&
		//这里如果带了& 就用带& 处理
		String nameToLookup = originalBeanName(name);
		返回 parentBeanFactory.getBean(nameToLookup, args);
	}
	
	if (parentBeanFactory == nul){
		//获取RootBeanDefinition 因为在上一步已经有缓存了这里直接拿到了
		RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
		if (mbd.getDependsOn()有值) {创建DependsOn内的Bean}
		//不同scope调用不同的创建策略
		case 单例 :  
			sharedInstance = getSingleton(beanName, 创建Bean(createBean(beanName, mbd, args)));
			beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); 
		break;
	}
	//这里其实就是看下Bean实例是不是你需要的类型
	//也就是 getBean(name, class)中的class类型
	//如果不是则调用Converter尝试进行转化
	return 适配BeanInstance
}
转化BeanName(transformedBeanName(name))
if (& 开头) {把所有的&去掉}
//这里就是查到别名映射的最终的BeanName
while(resolvedName = this.aliasMap.get(canonicalName) 且 resolvedName != null) {
	canonicalName = resolvedName;
}

createBean(beanName, mbd, args)

真实的创建Bean的逻辑
分析的代码是:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])

入参为:
String beanName, RootBeanDefinition mbd, @Nullable Object[] args

//重新赋值一个 RootBeanDefinition mbdToUse
//这里为啥要复制一个出来用 我的想法是避免别的地方修改原有的对象对我造成影响
RootBeanDefinition mbdToUse = mbd;
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);

if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
	mbdToUse = new RootBeanDefinition(mbd);
	//这里之前setBeanClass是把类的name放进去了 在这里改为把Class对象放进去
	mbdToUse.setBeanClass(resolvedClass);
}

//进入 beforeInstantiationResolved(String beanName, RootBeanDefinition mbd)
//这个属性是RootBeanDefinition自己的 Spring默认是没有赋值的
if (mbd.beforeInstantiationResolved == null || == true) {
	//这里InstantiationAwareBeanPostProcessors是有值的
	if(hasInstantiationAwareBeanPostProcessors()) {
		获取目标Class类型 = mbd.getTargetType()this.resolvedTargetType
		//这里是给自定义Bean一个机会 如果这里有任何一个返回就直接作为最终Bean了
		//Spring 默认在这里没有返回的
		遍历处理器 InstantiationAwareBeanPostProcessor:bp{
			Object result =  bp.postProcessBeforeInstantiation(beanClass, beanName)
			if (result != null) {
				//这里赶紧再执行下初始化后置处理器方法
				//因为实例化已经被处理器拦截了 走不动后边了
				bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
				//这个对象就是放在容器里的Bean了
				return result ;
			}
		}
	}
} 
	
//进入doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
//没有被实例化前处理器拦截的化就进去正式的实例化
BeanWrapper instanceWrapper = null;
if(是单例) {instanceWrapper=从factoryBeanInstanceCache获取一下}
if(instanceWrapper == null){
	instanceWrapper = 创建Bean实例(createBeanInstance(beanName, mbd, args)}
//到这里 instanceWrapper 就默认不是null了 因为后续就直接用了
mbd.resolvedTargetType = instanceWrapper.getWrappedClass();
//这里的处理器是给修改 mbd 一个机会
遍历处理器 MergedBeanDefinitionPostProcessor :processor {
	processor.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}

//属性填充
populateBean(beanName, mbd, instanceWrapper);
//初始化
exposedObject = initializeBean(beanName, exposedObject, mbd);
//注册bean销毁相关
registerDisposableBeanIfNecessary(beanName, bean, mbd);
return exposedObject;
resolveBeanClass(mbd, beanName)

根据className获取class

//这里其实beanClass还保存的ClassName 不是一个Class
if (mbd.beanClass instanceof Class) { return mbd.beanClass}
String className = mbd.beanClass;
evaluated = el表达式解析器解析处理下 className
if(className != null) {return beanClassLoader.loadClass(className);}
//到这里说明没有特别设置className那就正常解析
Class<?> resolvedClass = ClassUtils.forName(className, classLoader);
this.beanClass = resolvedClass;
return resolvedClass;
createBeanInstance(beanName, mbd, args)
//这一次经过上边的解析 mbd.beanClass 已经是个对象所以直接返回了
获取 Class 的对象 : resolvedClass (resolveBeanClass(mbd, beanName))
//这里行为参数化 你要自定义了实例方法就用你设置的实例创建方法创建
if (mbd.getInstanceSupplier() != null) {return Supplier.get()}
//默认没有值
if (mbd.getFactoryMethodName() != null) {return 指定工厂方法创建}
//这里大致意思就是 如果 args传值就用传入的值来推断下带参构造方法实例化
if (args == null && mbd.resolvedConstructorOrFactoryMethod != null) {return autowireConstructor(beanName, mbd, null, null);}
//如果构造器上有@Autowired
遍历处理器 SmartInstantiationAwareBeanPostProcessor bp {
	Constructor<?>[] ctors = bp.determineCandidateConstructors(beanClass, beanName);
	if (ctors != null) {
		return ctors;
	}
}
if (ctors != null) {return autowireConstructor(beanName, mbd, ctors, args);}
//走到这里就是后置处理器没有设置 也没有带@Autowired 那就用配置的默认构造器
//这里Spring 还没想好咋实现 直接就是返回 null
if ((ctors = mbd.getPreferredConstructors()) != null) {return autowireConstructor(beanName, mbd, ctors, args);}
//到这里就是用 无参构造器创建了
return instantiateBean(beanName, mbd);
populateBean(beanName, mbd, instanceWrapper)

instanceWrapper 中包含了已经实例化的对象

遍历处理器 InstantiationAwareBeanPostProcessor bp {
	if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
		//如果到这里就阻断属性赋值流程了
		return;
	}
}
PropertyValues pvs = mbd.getPropertyValues();
//如果有后置处理器设置了PropertyValues 就把这个设置给pvs 默认是没有的
//但是这里有一个AutowiredAnnotationBeanPostProcessor会处理@Autowired、@Value
遍历处理器 InstantiationAwareBeanPostProcessor bp {
	PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
	pvs = pvsToUse;
}
if (pvs.isEmpty()) {return;}

initializeBean(beanName, exposedObject, mbd)
//这里提前处理了三个Aware
//BeanNameAware\BeanClassLoaderAware\BeanFactoryAware
invokeAwareMethods(beanName, bean);

Object wrappedBean = bean;
遍历处理器 BeanPostProcessor processor {
	Object current = processor.postProcessBeforeInitialization(result, beanName);
	//current == null 直接 return
	wrappedBean = current;
}
if (bean instanceof InitializingBean) {bean.afterPropertiesSet();}
if ((String initMethodName = mbd.getInitMethodName()) != null) {调用InitMethodName}
//AOP就是在这里把对象替换成了代理对象
遍历处理器 BeanPostProcessor processor{
	Object current = processor.postProcessAfterInitialization(result, beanName);
	//current == null 直接 return
	wrappedBean = current;
}
return wrappedBean;
registerDisposableBeanIfNecessary(beanName, bean, mbd)

注册Bean的销毁方法 到 disposableBeans
在容器销毁的时候调用

  1. context.close()
  2. context.registerShutdownHook()
if (非多例 && 需要销毁(requiresDestruction(bean, mbd))) {
	if (单例的) {
		//设置到缓存中Map<String, Object> disposableBeans
		this.disposableBeans.put(beanName, bean);
	} else {
		//这里就是调用scope自己实现的销毁注册回调方法
		Scope scope.registerDestructionCallback()
	}
}

//主要是判断是否需要销毁
requiresDestruction(bean, mbd) {
	if (bean instanceof DisposableBean || instanceof AutoCloseable) return true;
	if (beanDefinition.resolvedDestroyMethodName isNotBlank) return true;
	if ("(inferred)".equals(beanDefinition.destroyMethodName)) {
		destroyMethodName = beanClass.hasMethod("close") || beanClass.hasMethod("shutdown");
		if (destroyMethodName isNotBlank) {
			beanDefinition.resolvedDestroyMethodName = destroyMethodName;
			return true;
		}
	}
	//这里其实就是看是否有 @PreDestroy in InitDestroyAnnotationBeanPostProcessor
	//InitDestroyAnnotationBeanPostProcessor 是 MergedBeanDefinitionPostProcessor
	//所以在之前执行postProcessMergedBeanDefinition方法时就解析了注解的方法
	遍历处理器 DestructionAwareBeanPostProcessor processor{
		if (processor.requiresDestruction(bean)) {
			return true;
		}
	}	
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值