spring5.3 三:Bean的生命周期源码解析上

Bean的生命周期源码解析上

Spring最重要的功能就是帮助程序员创建对象(也就是IOC),而启动Spring就是为创建Bean对象做准备,所以我们先明白Spring到底是怎么去创建Bean的,也就是先弄明白Bean的生命周期。
Bean的生命周期就是指:在Spring中,一个Bean是如何生成的,如何销毁的。
Bean生命周期流程图:https://www.processon.com/view/link/5f8588c87d9c0806f27358c1

Bean的生成过程

根据上面流程图,要想生成bean,首先要生成对应的BeanDefinition

生成BeanDefinition

扫描流程
在生成BeanDefinition之前,肯定是 需要扫描哪些类需要生成BeanDefinition。AnnotationConfigApplicationContextscandoScan。就是主要扫描过程。

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
		Assert.notEmpty(basePackages, "At least one base package must be specified");
		Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
		for (String basePackage : basePackages) {
			//核心的扫描逻辑 把扫描到的符合条件的类生成BeanDefinition的集合
			Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
			for (BeanDefinition candidate : candidates) {
				//获取scope的属性值(是单例的还是原型的)
				ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
				//设置bean的名称
				// 大致过程就是判断有没有org.springframework.stereotype.Component注解,有的话就获取value
				// 如果获取不到value值就构建一个默认的名称。默认构建过程中会对类名做字符串处理,返回一个beanName
				String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
				if (candidate instanceof AbstractBeanDefinition) {
					//设置一些默认值
					postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
				}
				if (candidate instanceof AnnotatedBeanDefinition) {
					// 处理@Lazy、@Primary、@DependsOn、@Role、@Description
					AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
				}
				//判断beanName是否已经存在
				if (checkCandidate(beanName, candidate)) {
					//判断通过后将BeanDefinition和beanName 封装成definitionHolder对象
					BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
					definitionHolder =
							AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
					beanDefinitions.add(definitionHolder);
					//最终会把definitionHolder中的BeanDefinition取出,和beanName 存入到beanDefinitionMap当中
					//到这里扫描主要的流程基本结束
					registerBeanDefinition(definitionHolder, this.registry);
				}
			}
		}
		return beanDefinitions;
	}

从上面代码来看 扫描过程主要分为这个部分

  1. 根据一定的逻辑扫描特定的资源然后以Set<BeanDefinition>形式返回
  2. 循环解析BeanDefinition 获取对应的scope、beanName、一些注解的处理等等
  3. 经过一些列处理将符合要求的BeanDefinition 封装成BeanDefinitionHolder
  4. 最后把BeanDefinitionHolder中的BeanDefinition 和beanName 存入到beanDefinitionMap

来看第一步 扫描的逻辑Set<BeanDefinition> candidates = findCandidateComponents(basePackage) 该方法中主要的是scanCandidateComponents(basePackage) 这个方法。这一部分是扫描的核心部分

private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
		Set<BeanDefinition> candidates = new LinkedHashSet<>();
		try {
			// 获取basePackage下所有的文件资源 CLASSPATH_ALL_URL_PREFIX的值是classpath*:
			//this.resourcePattern的值是**/*.class
			String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
					resolveBasePackage(basePackage) + '/' + this.resourcePattern;
			//获取classpath* 下包路径下的所有**/*.class 的资源
			Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
			boolean traceEnabled = logger.isTraceEnabled();
			boolean debugEnabled = logger.isDebugEnabled();
			//解析每个资源文件
			for (Resource resource : resources) {
				if (traceEnabled) {
					logger.trace("Scanning " + resource);
				}
				if (resource.isReadable()) {
					try {
						//通过Resource获取类的元数据信息(包含类名、属性、注解等等)
						MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
						// excludeFilters、includeFilters判断、@Conditional的条件判断 
						if (isCandidateComponent(metadataReader)) {
							//当判断是一个bean之后,创建一个ScannedGenericBeanDefinition
							//这个构造方法中把setBeanClassName(this.metadata.getClassName())放入到BeanDefinition中
							// 从metadataReader获取到getAnnotationMetadata--AnnotationMetadata
							// 放入到ScannedGenericBeanDefinition 提过给第二次判断
							ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
							//在后续过程中,当beanName相同是会通过Source判断是否兼容
							sbd.setSource(resource);
							//第二次判断 判断独立性、接口等等
							if (isCandidateComponent(sbd)) {
								if (debugEnabled) {
									logger.debug("Identified candidate component class: " + resource);
								}
								candidates.add(sbd);
							}
							else {
								if (debugEnabled) {
									logger.debug("Ignored because not a concrete top-level class: " + resource);
								}
							}
						}
						else {
							if (traceEnabled) {
								logger.trace("Ignored because not matching any filter: " + resource);
							}
						}
					}
					catch (Throwable ex) {
						throw new BeanDefinitionStoreException(
								"Failed to read candidate component class: " + resource, ex);
					}
				}
				else {
					if (traceEnabled) {
						logger.trace("Ignored because not readable: " + resource);
					}
				}
			}
		}
		catch (IOException ex) {
			throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
		}
		return candidates;
	}

这一部分的扫描流程是:通过ASM技术解析每个class文件封装成Source对象,遍历每个Resource对象,通过MetadataReader获取到元数据信息。isCandidateComponent(metadataReader)底层是进行excludeFilters和includeFilters,以及条件注解@Conditional的筛选。筛选通过后,基于metadataReader生成ScannedGenericBeanDefinition。这个过程中把类名放入Object beanClass中。接着isCandidateComponent(sbd) 基于ScannedGenericBeanDefinition判断这个class是不是接口或者抽象类等情况。如果不是接口也不是抽象类的话通过candidates.add(sbd);加入到集合当中

第二步,扫描核心逻辑结束后拿到BeanDefinition集合后,循环处理BeanDefinition。获取BeanDefinition的scope属性,根据BeanDefinition获取到beanName,对BeanDefinition设置一些默认值,判断BeanDefinition有没有@Lazy、@Primary等注解。最后判断beanName是否已经存在。

第三步 通过上述对BeanDefinition的处理后,把满足条件的BeanDefinition封装成BeanDefinitionHolder

第四步 registerBeanDefinition(definitionHolder, this.registry) 解析BeanDefinitionHolder,从BeanDefinitionHolder中获取到beanName和BeanDefinition放入到beanDefinitionMap 当中。到此整个扫描流程基本结束。

Spring扫描底层流程:https://www.processon.com/view/link/61370ee60e3e7412ecd95d43

合并BeanDefinition

扫描完成后接下来看AnnotationConfigApplicationContext的refresh()方法,先来看finishBeanFactoryInitialization(beanFactory);这行代码,主要是创建非懒加载的单例bean。该方法里面的核心方法beanFactory.preInstantiateSingletons();

	public void preInstantiateSingletons() throws BeansException {
		if (logger.isTraceEnabled()) {
			logger.trace("Pre-instantiating singletons in " + this);
		}
		//扫描的时候会把beanName放入到List当中
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
		// Trigger initialization of all non-lazy singleton beans...
		for (String beanName : beanNames) {
			//这行代码开始合并BeanDefinition并且获取合并后的BeanDefinition
			// 在spring中支持父子BeanDefinition 子BeanDefinition需要从父BeanDefinition中获取信息
			// 因此创建子BeanDefinition对应的bean时需要进行父子BeanDefinition合并,得到完整子的BeanDefinition也就是RootBeanDefinition
			// 同时把RootBeanDefinition放入到Map<String, RootBeanDefinition>中
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			//当合并后的BeanDefinition 符合单例bd.isSingleton()
			// 非懒加载!bd.isLazyInit() 非抽象!bd.isAbstract() 时 最后调用getBean(beanName)
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
				if (isFactoryBean(beanName)) {
					// 获取FactoryBean对象
					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
					if (bean instanceof FactoryBean) {
						FactoryBean<?> factory = (FactoryBean<?>) bean;
						boolean isEagerInit;
						//判断是否开启安全管理器  不用管  直接看else的代码
						if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
							isEagerInit = AccessController.doPrivileged(
									(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
									getAccessControlContext());
						}
						else {
							//判断这个bean是否实现的是SmartFactoryBean接口  如果实现了 在判断是否重写了isEagerInit,默认返回false
							//如果重写了isEagerInit 并且放回true 则调用getBean创建对象
							//SmartFactoryBean 是 FactoryBean的子接口
							isEagerInit = (factory instanceof SmartFactoryBean &&
									((SmartFactoryBean<?>) factory).isEagerInit());
						}
						if (isEagerInit) {
							// 创建真正的Bean对象(getObject()返回的对象)
							getBean(beanName);
						}
					}
				}
				else {
					// 创建Bean对象
					getBean(beanName);
				}
			}
		}
		// 所有的非懒加载单例Bean都创建完了后
		// Trigger post-initialization callback for all applicable beans...
		for (String beanName : beanNames) {
			//当单例bean创建好之后会放入到单例池当中,而下面这个方法就是从单例池当中获取单例bean
			Object singletonInstance = getSingleton(beanName);
			//判断单例bean有没有实现SmartInitializingSingleton接口  有的话调用重写的方法(afterSingletonsInstantiated)
			//注意afterSingletonsInstantiated方法是在所有单例bean都创建好之后,才开始调用每一个实现了SmartInitializingSingleton接口的方法
			if (singletonInstance instanceof SmartInitializingSingleton) {
				StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
						.tag("beanName", beanName);
				SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
				if (System.getSecurityManager() != null) {
					AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
						smartSingleton.afterSingletonsInstantiated();
						return null;
					}, getAccessControlContext());
				}
				else {
					//调用重写SmartInitializingSingleton接口的方法
					smartSingleton.afterSingletonsInstantiated();
				}
				smartInitialize.end();
			}
		}
	}

通过扫描得到所有BeanDefinition之后,就可以根据BeanDefinition创建Bean对象了。但是在Spring中支持父子BeanDefinition,类似于

这么定义的情况下,child是单例Bean
<bean id="parent" class="com.zhouyu.service.Parent" scope="prototype"/>
<bean id="child" class="com.zhouyu.service.Child"/>
这么定义的情况下,child就是原型Bean
<bean id="parent" class="com.zhouyu.service.Parent" scope="prototype"/>
<bean id="child" class="com.zhouyu.service.Child" parent="parent"/>

所以需要进行BeanDefinition的合并,得到完整的BeanDefinition。合并完BeanDefinition后会得到RootBeanDefinition,根据这个RootBeanDefinition判断是否懒加载,抽象类等等,最后通过getBean(beanName)方法创建非懒加载的单例bean。所有的bean都创建完成后判断有没有实现SmartInitializingSingleton接口 如果有的话调用afterSingletonsInstantiated方法 。

下一篇会对getBean(beanName)方法进行分析。到目前为止,从spring的源码中可以学习到两个扩展点,一个是扫描逻辑里面有一个判断@Conditional的注解,一个是bean 实现SmartInitializingSingleton接口 重写afterSingletonsInstantiated

扩展点案例

@Conditional

@Service
@Conditional(GoodsConditional.class)
public class GoodsServiceImpl {
	public void test(){
		System.out.println("GoodsServiceImpl---------test");
	}
}
//如果返回false 表示不创建该bean,返回true表示创建该bean 所以可以在这里写判断逻辑
public class GoodsConditional implements Condition {
	@Override
	public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
		System.out.println("11111");
		return true;
	}
}

SmartInitializingSingleton

@Service
@Conditional(GoodsConditional.class)
public class GoodsServiceImpl implements SmartInitializingSingleton {
	public void test(){
		System.out.println("GoodsServiceImpl---------test");
	}
	@Override
	public void afterSingletonsInstantiated() {
		System.out.println("创建完成单例bean后:执行了GoodsServiceImpl 的 afterSingletonsInstantiated 方法");
	}
}

测试

//扫描该路径
@ComponentScan("service")
public class AppConfig {

}
public class Test {
	public static void main(String[] args) {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
		Object obj = context.getBean("goodsServiceImpl");
		GoodsServiceImpl goodsService = (GoodsServiceImpl)obj;
		goodsService.test();
	}
}

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值