Spring Bean 的生命周期

博文目录


内容总结

关于扫描与注册 BeanDefinition

扫描流程

入口是在 refresh 的 invokeBeanFactoryPostProcessors 流程中, 这里会拿到 ConfigurationClassPostProcessor 并由它来解析配置类, 在解析到 @ComponentScan 注解时, 根据解析获得的 basePackages 调用 ClassPathBeanDefinitionScanner.doScan 来扫描包路径. 拿到全部的 class 文件(Resource), 通过 ASM 技术解析每一个 Resource 文件获得其元数据信息 MetadataReader, 通过 excludeFilters 和 encludeFilters 和 @Conditional 条件的判断, 生成 ScannedGenericBeanDefinition 对象, 再通过独立和具体等条件的判断, 最终将通过判断的 BeanDefinition 加入结果集返回.

遍历结果集, 解析其 Scope 是单例还是原型, 获取并设置 beanName, 给 BeanDefinition 设置一些默认值, 解析 @Lazy, @Primary, @DependsOn 等, 最后再次判断 BeanDefinition 是否已经存在, 存在的话判断新旧是否兼容, 只有通过检测, 才会被注册到 beanDefinitionMap 中

关于创建非懒加载的 Bean

创建流程

入口是在 refresh 的 finishBeanFactoryInitialization 流程中, 遍历所有的 BeanName, 根据 BeanName 拿到合并后(父子关系会继承一些配置)的 RootBeanDefinition, 校验非懒加载单例, 普通的直接调用 getBean 创建并存入单例池, FactoryBean 的先 getBean 创建 FactoryBean 本身, 存到单例池(BeanName 没有 & 符号), 再判断是否需要通过调用 getBean 的方式调用 getObject(getBean 内部会判断是否为 FactoryBean), FactoryBean.getObject 创建的 Bean 不是存到单例池, 而是存到 factoryBeanObjectCache Map 中, 其 Key(BeanName) 和 该FactoryBean 的相同

getBean 目标是返回一个 Bean, 其内部对 FactoryBean 有特殊的处理逻辑, 不管是从单例池中取出来的 Bean 还是刚刚创建好的 Bean, 都会走一波针对 FactoryBean 的特殊流程. 根据调用 getBean 的目的(如果传入的 name 前面有 & 则说明目的是获取 FactoryBean 本身)和 Bean 的实际类型, 把 Bean 分为三种情况来处理, 和 FactoryBean 无关的普通 Bean 直接返回, 要获取 FactoryBean 本身的返回其本身, 要获取 FactoryBean 的 getObject Bean 的, 则再调用 FactoryBean 的 getObject 方法获取 Bean(只经过实例化后(AOP)处理), 缓存起来, 然后再返回

接下来就是 getBean 了, 无 Bean 创建并返回, 有 Bean 直接返回. 首先解析 BeanName, 就是把别名转成 BeanName, 把 FactoryBean 的 & 开头的名字转成 BeanName, 根据 BeanName 到单例池中取, 如果取到了, 则针对 FactoryBean 的情况做下处理. 如果没有取到, 获取合并后的 BeanDefinition, 针对 @DependsOn 的 Bean 做 getBean, 根据 Scope 单例/原型/其他 分别调用 createBean 来创建 Bean, 单例的会多一步缓存到单例池的步骤, 原型的创建好直接返回(每次 getBean 都创建, 返回的不一样), 其他的先不管. 最终返回结果前, 判断拿到的 Bean 和需求的 Bean 类型是否匹配, 不匹配的能否转换

接下来就是 createBean 了, 大致流程如下

  • 类加载, 因为 BeanDefinition 扫描解析都是用的 ASM 技术, 并没有经过 JVM 加载类得到 Class 对象, BeanDefinition 的 beanClass 字段里存的都是类的全限定名, 在这一步要改成 Class
  • 实例化前, BeanPostProcessor.postProcessBeforeInstantiation, 如果这里返回非空对象, 会把该对象认为是 Bean(仍然会做实例化后(AOP)处理), createBean 直接结束
  • 实例化, 包含 Supplier, 工厂方法, 推断构造方法等
  • BeanPostProcessor.postProcessMergedBeanDefinition, 这里会完成 AutowiredAnnotationBeanPostProcessor 寻找依赖注入点
  • 实例化后, BeanPostProcessor.postProcessAfterInstantiation, 这个用的很少
  • 依赖注入, 分默认的 ByName/ByType 和通过 BeanPostProcessor.postProcessProperties 两种实现方式, AutowiredAnnotationBeanPostProcessor 处理 @Autowired 和 @Value, CommonAnnotationBeanPostProcessor 处理 @Resource
  • 执行几个 Aware 注入
  • 初始化前, BeanPostProcessor.postProcessBeforeInitialization, 这里会完成 InitDestroyAnnotationBeanPostProcessor 处理 @PostConstruct 注解, ApplicationContextAwareProcessor 处理剩余 Aware 的注入
  • 初始化, 调用 InitializingBean 的 afterPropertiesSet 方法, 调用自定义的初始化方法
  • 初始化后, BeanPostProcessor.postProcessAfterInitialization, AOP 就是这里实现的, 初始化后返回的对象才是最终的 Bean 对象. 所有创建的 Bean 都会经过初始化后操作
  • 然后是需要在容器关闭时执行销毁操作的 Bean 的注册

关于销毁 Bean

在 getBean 的最后一步, 就是判断当前 Bean 是否需要在容器关闭时执行指定的销毁方法, 该判断只针对单例和其他, 不支持原型. 某个 Bean 是 DisposableBean, 或有 @PreDestroy 注解的方法, 就会被认为是需要销毁, @PreDestroy 由 InitDestroyAnnotationBeanPostProcessor 这个 BeanPostProcessor 提供解析实现, 提供判断是否需要认定需要销毁. 然后把需要执行销毁的 Bean 都包装成为 DisposableBeanAdapter(实现了 DisposableBean, 有 destroy 方法) 并缓存起来, 其 destroy 方法可以针对各种情况的销毁方法做统一执行处理. 待容器关闭时, 直接调用缓存的 DisposableBeanAdapter 的 destroy 方法即可

然后是在容器关闭时, 调用 doClose 走销毁流程, 先把刚刚缓存的 DisposableBeanAdapter 都拿到, 调用其 destroy 方法执行通过各种方式定义的销毁方法, 然后再清空整个单例池. 在销毁 DisposableBeanAdapter 的时候, 会先根据 Bean 的互相依赖关系, 把所有依赖当前 Bean 的 Bean 优先销毁, 类似依赖注入的递归

Spring 以 Annotation 方式运行

Spring 以 Annotation 方式启动的入口如下, 新建 AnnotationConfigApplicationContext, 同时传入一个配置类, 内部调用无参构造函数, 给字段 AnnotatedBeanDefinitionReader 和 ClassPathBeanDefinitionScanner 赋值, 然后注册传入的配置类, 然后调用 Spring 模板方法 refresh 来启动整个容器

Spring 会先使用 ClassPathBeanDefinitionScanner 扫描指定包路径下的 BeanDefinition, 然后把其中非懒加载的单例 BeanDefinition 创建并注册成为 Bean 对象, 缓存在单例池(singletonObjects)中

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Application.class);
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
	this();
	register(componentClasses);
	refresh();
}
public AnnotationConfigApplicationContext() {
	// ...
	this.reader = new AnnotatedBeanDefinitionReader(this);
	// ...
	this.scanner = new ClassPathBeanDefinitionScanner(this);
}

虽然上面创建了一个 ClassPathBeanDefinitionScanner, 但是其仅仅是为了 AnnotationConfigApplicationContext 的下面这个构造器扫描 basePackages 服务的, 我们传入的是配置类而不是字符串数组, 所以我们并不会使用到这个 Scanner, 我们使用的是该类的另一个实例对象

public AnnotationConfigApplicationContext(String... basePackages) {
	this();
	scan(basePackages);
	refresh();
}

扫描入口

Spring 以 Annotation 方式运行时扫描 BeanDefinition 是通过 ClassPathBeanDefinitionScanner.doScan() 来完成的. 执行的位置是在 refresh 方法的 invokeBeanFactoryPostProcessors(beanFactory) 流程中. 在这里会找到 ConfigurationClassPostProcessor(解析配置类), 调用其作为 BeanDefinitionRegistryPostProcessorpostProcessBeanDefinitionRegistry 方法来解析配置类, 流程包括解析 @ComponentScan 注解, 得到最终的 basePackages, 然后调用 Scanner.doScan 来扫描

大致流程

  • refresh
  • invokeBeanFactoryPostProcessors(beanFactory), refresh 中的一个流程
  • PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors()
  • beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false) 会获取到实现了 BeanDefinitionRegistryPostProcessor 接口的 ConfigurationClassPostProcessor(解析配置类), 其实现了 PriorityOrdered 接口, 会被优先处理
  • invokeBeanDefinitionRegistryPostProcessors(), 优先调用 ConfigurationClassPostProcessor 作为 BeanDefinitionRegistryPostProcessor 实现的 postProcessBeanDefinitionRegistry 方法
  • ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry()
  • ConfigurationClassParser.parse(), 解析配置类
  • ConfigurationClassParser.doProcessConfigurationClass(), 解析 @ComponentScans 注解
  • ComponentScanAnnotationParser.parse(), 解析 @ComponentScan 注解的 basePackages 和 basePackageClasses 属性, 如果都没有指定, 则拿到配置类的包路径作为默认的 basePackages
  • ClassPathBeanDefinitionScanner.doScan(), 扫描最终的 basePackages

扫描过程

扫描流程

核心就是 ClassPathBeanDefinitionScanner.doScan 方法中的 scanCandidateComponents 方法

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);
		// BeanDefinition 的后续赋值操作, 生成 beanName, 校验其他条件等
		for (BeanDefinition candidate : candidates) {
			// 解析 Scope, 单例/原型
			ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
			candidate.setScope(scopeMetadata.getScopeName());
			// beanName, AnnotationBeanNameGenerator.generateBeanName
			String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
			if (candidate instanceof AbstractBeanDefinition) {
				// 给 BeanDefinition 赋一些默认值, 懒加载什么的
				postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
			}
			if (candidate instanceof AnnotatedBeanDefinition) {
				// 解析 @Lazy, @Primary, @DependsOn, @Role, @Description, 后面两个没有太大作用
				AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
			}
			// 检查容器中是否已经存在该 beanName, 如果存在且兼容, 则该 BeanDefinition 还是会被忽略
			if (checkCandidate(beanName, candidate)) {
				BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
				definitionHolder =
						AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
				beanDefinitions.add(definitionHolder);
				// 注册 BeanDefinitionHolder 中的 BeanDefinition, 即 BeanFactory 中的 beandefinitionMap
				registerBeanDefinition(definitionHolder, this.registry);
			}
		}
	}
	return beanDefinitions;
}
public Set<BeanDefinition> findCandidateComponents(String basePackage) {
	if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
		return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
	} else {
		return scanCandidateComponents(basePackage);
	}
}

静态索引机制

在 doScan 中通过 findCandidateComponents 即可扫描到所有的 BeanDefinition, 其中有两个分支, 上面的分支是 Spring 提供的一种快速启动应用程序的方法, 原理就是创建一个索引文件, 告诉 Spring 哪些类是 BeanDefinition, 代替扫描的流程, 这样在类文件巨多的场景下能提升启动性能. 知道这个方法就可以了, 平时很少用到, 该方法的具体描述如下

虽然类路径扫描非常快, 但通过在编译时创建候选的静态列表, 可以提高大型应用程序(类非常多)的启动性能. 在此模式下, 应用程序的所有模块都必须使用此机制, 当 ApplicationContext 检测到此类索引时, 它将自动使用它, 而不是扫描类路径. 启用方式就是 pom 中引入 spring-context-indexer 依赖, 这个过程将需要一个名为 META-INF/spring.components 的文件, 并将其包含在jar包中. 如果在类路径中找到 META-INF/spring.components 时, 将自动启用索引. 也可以通过设置 spring.index.ignore 来配置是否启用索引

动态扫描机制

核心就是 ClassPathScanningCandidateComponentProvider#scanCandidateComponents

大致流程

  • 拿到扫描路径, 如 classpath*:com/coder/main/**/*.class
  • 通过 ResourcePatternResolver 拿到各级目录下的全部 class 文件, 包装成为 Resource 对象
  • 遍历每个 Resource 对象, 利用 MetadataReaderFactory 解析 Resource 得到对应的 MetadataReader, MetadataReaderFactory 具体为 CachingMetadataReaderFactory, MetadataReader 具体为 SimpleMetadataReader
  • 根据 MetadataReader 的信息判断该 Resource 是否为符合条件的候选组件, 只有不被 excludeFilters 排除且同时被 includeFilters 包含, 且满足 @Conditional 注解指定条件(没有该注解的算满足条件), 满足这样条件的资源才是候选组件
    • 在创建 ClassPathBeanDefinitionScanner 的时候会调用 registerDefaultFilters 注册默认的过滤器, 其中 includeFilters 会注册如下过滤器, 默认不注册 excludeFilters
      • 匹配 @Component 注解的 AnnotationTypeFilter
      • 匹配 @ManagedBean 注解的 AnnotationTypeFilter, 如果类 javax.annotation.ManagedBean 存在的话
      • 匹配 @Named 注解的 AnnotationTypeFilter, 如果类 javax.inject.Named 存在的话
    • 在 ConfigurationClassPostProcessor 解析配置类的 @ComponentScan 注解结束后, 调用 Scanner.doScan 之前, 会给 Scanner 添加一个 AbstractTypeHierarchyTraversingFilter, 会判断资源的全限定类名, 如果和配置类相同, 则排除该资源
  • 筛选通过后, 基于 MetadataReader 生成 ScannedGenericBeanDefinition
  • 再基于 ScannedGenericBeanDefinition 获取到的 AnnotationMetadata 判断其是否符合条件, (是独立的 || (是具体的 || (是抽象的 && 有 @Lockup 注解的方法)))
    • 是独立的: 即加载该类不需要依赖其他类, 符合条件的只有 顶级类(一个文件里只有这一个了) 和 静态内部类, 普通内部类需要先实例化一个外部类, 才能创建内部类, 如 User user = new User(); User2 user2 = user.new User2();
    • 是具体的: 非抽象类, 非接口
  • 通过筛选后, 表明是一个 Bean, 将 ScannedGenericBeanDefinition 加入到结果集, 返回

CachingMetadataReaderFactory 解析某个 class 文件得到 MetadataReader 对象, 是利用的 ASM 技术, 并没有加载这个类到 JVM. 并且最终得到的 ScannedGenericBeanDefinition 对象, 其 beanClass 属性存储的是当前类的全限定名, 而不是 class 对象(要拿到 Class 对象就必须得经过 JVM 加载). (beanClass 属性的类型是 Object, 即可以存储类的名字, 也可以存储 class 对象)

上面的流程是通过扫描拿到 BeanDefinition, 还可以通过 自定义 BeanDefinition, 解析 spring.xml 的 < bean>, @Bean 注解 等方式注册 BeanDefinition

动态扫描后续

拿到符合条件的 BeanDefinition 结果集后, 并不会直接注册, 还有后续流程, 如解析其 Scope 是单例还是原型, 获取并设置 beanName, 给 BeanDefinition 设置一些默认值, 解析 @Lazy, @Primary, @DependsOn 等, 最后再次判断 BeanDefinition 是否已经存在, 存在的话判断新旧是否兼容, 只有通过检测, 才会被注册到 beanDefinitionMap 中

创建

Spring 实例化剩余非懒加载的 Bean 的入口是在 refreshfinishBeanFactoryInitialization 方法的 beanFactory.preInstantiateSingletons(), 最终调用的是 DefaultListableBeanFactory.preInstantiateSingletons

全部非懒加载的单例 Bean 将在这里被实例化, 包括普通 Bean 和 FactoryBean, FactoryBean 的 getObject Bean 默认是懒加载的, 不会在这里被调用 getBean 从而被实例化. 但是可通过让 FactoryBean 实现 SmartFactoryBean 接口, 复写 isEagerInit 方法并返回 true, 这样 FactoryBean 的 getObject Bean 也会在这里被调用 getBean 从而被实例化

大致流程

在真正调用 getBean 之前还有一些流程如下

  • DefaultListableBeanFactory.preInstantiateSingletons
  • 遍历 beanDefinitionNames
  • 合并 BeanDefinition
  • 校验 BeanDefinition 非抽象, 是单例, 非懒加载, 不是的直接跳过
  • 判断 beanName 是否为 FactoryBean
      • 先通过 &BeanName 执行 getBean 获取到 FactoryBean 本身, 存入单例池
      • 判断 FacotryBean 是否实现了 SmartFactoryBean, 是的话, 判断其 isEagerInit, 是的话则通过 BeanName 执行 getBean 获取 FactoryBean 的 getObject Bean, 缓存到 factoryBeanObjectCache 中
    • 否, 通过 BeanName 执行 getBean 获取到普通 Bean 本身, 存入单例池
  • 在所有非懒加载的单例 Bean 被创建后, 再次遍历 beanDefinitionNames
  • 从单例池中获取到对应的单例 Bean, 判断其是否实现了 SmartInitializingSingleton 接口
    • 实现的话则调用其 afterSingletonsInstantiated 方法
@Override
public void preInstantiateSingletons() throws BeansException {
	if (logger.isTraceEnabled()) {
		logger.trace("Pre-instantiating singletons in " + this);
	}

	// Iterate over a copy to allow for init methods which in turn register new bean definitions.
	// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
	List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

	// Trigger initialization of all non-lazy singleton beans...
	// 扫描 BeanDefinition 加入 beanDefinitionMap 时会把对应的 BeanName 也存到 List beanDefinitionNames 中
	for (String beanName : beanNames) {

		// Spring 支持配置父子关系的 BeanDefinition
		// 子 BeanDefinition 可以先从父 BeanDefinition 中继承一些配置
		// 然后子 BeanDefinition 再用自己的配置覆盖一遍
		// 最终拿到的 BeanDefinition 才是用来创建 Bean 的 RootBeanDefinition
		// RootBeanDefinition 就代表没有父的最终的 BeanDefinitionMap
		// 注意一点, 合并是从父子 BeanDefinition 里拿到配置, 然后创建一个新的 RootBeanDefinition
		// 合并后的 RootBeanDefinition 会存到 mergedBeanDefinitions 中用来创建 Bean
		RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);

		// 非抽象, 是单例, 非懒加载 的 BeanDefinition 会被执行 实例化
		// BeanDefinition.isAbstract, 非抽象的 BeanDefinition, 而不是指该 BeanDefinition 对应的 Class 是抽象的
		// 通过 xml 配置的 BeanDefinition 可以配置成为抽象 abstract="true"
		// 抽象的 BeanDefinition 往往用在父子 BeanDefinition 中
		// 抽象的 BeanDefinition 不能生成 Bean, 但是可以被其他 BeanDefinition 继承其配置
		if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {

			// 如果是 FactoryBean 则走特殊逻辑
			if (isFactoryBean(beanName)) {

				// FactoryBean 的处理方式, 有如下两个步骤
				// 先通过 &BeanName 获取到 FactoryBean 本身, 缓存到单例池, 名称是 BeanName, 类型是 FactoryBean
				// 再通过 BeanName 获取到 getObject 的 Bean, 缓存到 factoryBeanObjectCache 中, 名称同样是 BeanName, 类型是对应的类型
				Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
				if (bean instanceof FactoryBean) {
					FactoryBean<?> factory = (FactoryBean<?>) bean;
					boolean isEagerInit;
					if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
						isEagerInit = AccessController.doPrivileged(
								(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
								getAccessControlContext());
					} else {
						isEagerInit = (factory instanceof SmartFactoryBean &&
								((SmartFactoryBean<?>) factory).isEagerInit());
					}
					// 实现了 SmartFactoryBean 接口的 FactoryBean, 覆盖了 isEagerInit 方法并返回 true, 才会在这里调用其 getObject 方法
					if (isEagerInit) {
						// 调用 FactoryBean 的 getObject 方法来创建 Bean
						getBean(beanName);
					}
				}
			} else {

				// 直接创建 Bean
				getBean(beanName);
			}
		}
	}

	// Trigger post-initialization callback for all applicable beans...
	// Bean 生命周期中的 初始化后 流程指的并不是这里
	// 所有非懒加载的单例 Bean 创建完之后
	for (String beanName : beanNames) {
		// 从单例池 singletonObjects 拿到单例 Bean
		Object singletonInstance = getSingleton(beanName);
		// 如果该单例 Bean 实现了 SmartInitializingSingleton 接口, 则调用其 afterSingletonsInstantiated 方法
		// 注意是所有非懒加载的单例 Bean 创建完缓存好之后, 才会再遍历调用所有单例 Bean 的这个方法
		if (singletonInstance instanceof SmartInitializingSingleton) {
			StartupStep smartInitialize = 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 {
				smartSingleton.afterSingletonsInstantiated();
			}
			smartInitialize.end();
		}
	}
}

合并 BeanDefinition

但是在实例化前还需要合并 BeanDefinition, Spring 支持配置父子关系的 BeanDefinition, 先创建一个全新的 RootBeanDefinition, 先从父 BeanDefinition 中继承一些配置, 然后再用子 BeanDefinition 的配置覆盖一遍, 最终拿到的 RootBeanDefinition 才是用来创建 Bean 的 BeanDefinition, 该 BeanDefinition 会被缓存到 mergedBeanDefinitions 中, getBean 的时候从这里拿

父子 BeanDefinition 使用的比较少, 知道这个点就行了, 举个例子: < bean> 里面的 parent 配置用来指向父 Bean

判断 FactoryBean

实现了 FactoryBean 接口的 Bean, 这样的 Bean 它本身是一个 Bean, FactoryBean 有一个 getObject 方法, 也能创建 Bean, 且也会被 Spring 管理起来(不是放在单例池, 而是在 factoryBeanObjectCache). 需要注意的是, 通过 getObject 创建的 Bean 没有经过 Spring 创建 Bean 的全部常规流程, 只会经过 初始化后(AOP) 流程, 没有 依赖注入 流程, 所以内部如果有其他字段, 是不会被执行注入的

通过 FactoryBean 名称获取到的 Bean 是 getObject 方法创建并被 Spring 管理的 Bean, 而通过 & 符号加 FactoryBean 名称获取到的 Bean 则是 FactoryBean 本身. 例如有如下配置, 通过 getBean(“userFactoryBean”) 获取到的是 User, 通过 getBean(“&userFactoryBean”) 获取到的则是 UserFactoryBean

@Component
public class UserFactoryBean implements FactoryBean<User> {
	@Override
	public User getObject() throws Exception {
		return new User();
	}
	@Override
	public Class<?> getObjectType() {
		return User.class;
	}
}

FactoryBean 本身会被存到单例池 singletonObjects 中, 而 FactoryBean 的 getObject 创建的 Bean 则会被存到 factoryBeanObjectCache 中, 两者的名称都是 FactoryBean 本身的 BeanName, 只是在 getBean 的时候, 会根据是否有 & 符号前缀做特殊的处理

FactoryBean 有一个子接口 SmartFactoryBean, 覆盖其 isEagerInit 方法并返回 true, 则在创建非懒加载的全部单例 Bean 的时候会调用 FactoryBean 的 getObject 方法创建对应 Bean, 默认不是在这个时候创建 getObject 的 Bean

调用 getBean

首次调用 getBean 会走创建 Bean 的流程, 然后缓存到单例池(FactoryBean 的 getObject Bean 会缓存在 factoryBeanObjectCache), 后续再次调用就会从缓存中拿

Spring 支持给 BeanName 起别名, 支持给别名再起别名, 在 BeanFactory 中有一个 aliasMap, 存放别名与 Name 的印射, 可通过别名获取到 BeanName 或者另一个别名, getBean 的时候, 先假设 name 是别名, 从 aliasMap 中获取, 将获取到的结果继续获取, 直到不存在, 说明此时的 name 就是 BeanName 了

getBean(beanName, Class< T>), 同时传入了 BeanName 与 Type, 流程同样是根据 BeanName 找到 Bean, 然后判断 Bean 类型与给定的 Type 是否匹配, 能否转换, 否则报错. 并不是按照传入的 type 去单例池中找这种类型的 Bean

大致流程

  • 内部调用 doGetBean
  • 根据传入的 name 解析成为 BeanName. 别名解析成为 BeanName, &BeanName 解析成为 BeanName
  • 尝试从单例池中获取该 BeanName 对应的 Bean
    • 存在
      • 调用 getObjectForBeanInstance 来处理 FactoryBean 的情况, 这就是 getBean 内部对 FactoryBean 的特殊处理流程
        • 如果是要获取 FactoryBean 本身, 即 &BeanName, 则校验 Bean 确实是一个 FactoryBean, 返回该 Bean
          • name 以 & 开头, 说明想获取 FactoryBean 本身, 当从单例池中拿到的 Bean 也是一个 FactoryBean 时, 直接返回
        • 如果是要获取与 FactoryBean 无关的普通 Bean, 直接返回该 Bean
          • name 非 & 开头, 说明不想获取 FactoryBean, 当从单例池中拿到的 Bean 不是一个 FacotryBean 时, 直接返回
        • 如果是要获取 FactoryBean 的 getObject 的 Bean, 则从 factoryBeanObjectCache 中检索, 有则返回, 无则调用 FactoryBean 的 getObject 创建该 Bean, 缓存到 factoryBeanObjectCache 中, 然后返回
          • name 非 & 开头, 且 Bean 是一个 FactoryBean, 说明想获取 FactoryBean 生成的 Bean, 这里同样也有缓存
    • 不存在, 走创建流程
      • 如果当前 BeanFactory 中没有对应的 BeanDefinition, 且存在 ParentBeanFactory, 则到 ParentBeanFactory 中 getBean 并返回
      • 获取合并的 BeanDefinition, 校验不是抽象的 BeanDefinition
      • 判断是否有 @DependsOn 关系, 有的话先 getBean 依赖的 Bean
      • 根据 Scope 走不同的创建流程
        • 单例, 调用 getSingleton, 调用 createBean, 然后存到单例池, 处理 FactoryBean, 返回 Bean
        • 原型, 直接 createBean, 处理 FactoryBean, 返回 Bean
        • 其他, …, 处理 FactoryBean, 返回 Bean

调用 createBean

createBean, 创建 Bean

大致流程

  • 类加载, resolveBeanClass
  • 实例化前, InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation
  • doCreateBean
    • 实例化, createBeanInstance
      • 推断构造方法
    • MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition, 提供修改 BeanDefinition 的能力
      • Spring 提供了一个默认实现, AutowiredAnnotationBeanPostProcessor, 在这里找到需要执行注入的字段和方法(@Autowired / @Value / javax.inject.Inject)并缓存起来, 后面依赖注入的时候就不用找了, 直接拿来用就行
    • 实例化后(基本没用), InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation, 在 populateBean 方法内部的最前面, 可以看成是实例化后发生在依赖注入前
    • 依赖注入(填充属性), populateBean
      • Spring 自带的依赖注入能力
      • 处理属性, InstantiationAwareBeanPostProcessor.postProcessProperties, 非常重要, @Autowired, @Resource, @value 都在这里解析
        • AutowiredAnnotationBeanPostProcessor 处理 @Autowired, @Value
        • CommonAnnotationBeanPostProcessor 处理 @Resource
    • 初始化, initializeBean
      • invokeAwareMethods, 调用 Aware, BeanNameAware, BeanClassLoaderAware, BeanFactoryAware
      • 初始化前, BeanPostProcessor.postProcessBeforeInitialization
        • InitDestroyAnnotationBeanPostProcessor, 处理 @PostConstruct 和 @PreDestroy 注解指定的方法, 拿到类, 遍历所有方法, 判断有无注解, 有则执行
        • ApplicationContextAwareProcessor, 调用剩余的 Aware
      • 初始化, invokeInitMethods
        • 调用 InitializingBean 的 afterPropertiesSet 方法
        • 调用自定义的 初始化方法(initMethod)
      • 初始化后, BeanPostProcessor.postProcessAfterInitialization
        • AOP 就是基于初始化后实现的, 初始化后返回的对象才是最终的 Bean 对象
    • 如有必要注册销毁信息, 不是所有 Bean 都需要走销毁流程, 所以有一个判断

销毁

判断是否需要销毁

在创建 Bean 的最后一步, 就是把最终需要执行销毁的 Bean 额外缓存起来, 最终销毁的时候, 统一执行销毁方法, 其位置是在 org.springframework.beans.factory.support.AbstractBeanFactory#registerDisposableBeanIfNecessary

大致流程

  • registerDisposableBeanIfNecessary
  • 过滤, 原型 Bean 不需要做销毁处理
  • 过滤, 判断 Bean 是否需要被销毁, 满足这两个条件的才会被缓存记录
    • 判断, 有销毁方法的
      • DisposableBean || (destroyMethodName 是 (inferred) || (未指定销毁方法但实现了 AutoCloseable)), 后者内只要有 close, shutdown 等方法都会被认为是销毁方法
    • 判断, 被我们认定为需要执行销毁的
      • 有 DestructionAwareBeanPostProcessor 的则执行其 requiresDestruction 返回是否认定某 Bean 需要被销毁
        • InitDestroyAnnotationBeanPostProcessor 处理 @PostConstruct 和 @PreDestroy, 带 @PreDestroy 方法的 Bean 就是在这一步被认定为需要执行销毁的
  • 将最终被认定为容器关闭时需要执行销毁的及到的 BeanName, BeanDefinition, Bean, BeanPostProcessor 都打包成为 DisposableBeanAdapter 缓存到 disposableBeans 中, 该 DisposableBeanAdapter 实现了 DisposableBean 接口, 就是一个 DisposableBean, 其 destroy 就是整合的销毁方法, 能够执行通过各种方式定义的销毁方法

触发 Bean 的销毁有两种方式

  • ApplicationContext.registerShutdownHook(), 在 JVM 里注册该应用的关闭钩子(线程), 当程序正常结束的时候会调用线程方法执行某些操作, 非正常结束时不能触发(kill -9, Idea Stop)
  • ApplicationContext.close(), 也可以手动触发关闭, 和注册钩子一样, 最后都是调用 Spring 的 doClose 方法

Bean 销毁流程

触发 Bean 销毁的入口在 org.springframework.context.support.AbstractApplicationContext#doClose, 内部有一个流程就是销毁所有单例 Bean, 即单例池也会被清空, 只不过需要执行销毁逻辑的 Bean 会先一步执行销毁方法

大致流程

  • doClose
  • destroyBeans, 销毁所有单例 Bean
  • destroySingletons, 销毁所有单例 Bean
  • 遍历缓存的需要走销毁逻辑的 disposableBeans, 其内元素都是 DisposableBeanAdapter , 调用 destroySingleton 销毁遍历到的 Bean
    • removeSingleton, 从单例池中把该 Bean 移除
    • destroyBean, 传入 DisposableBeanAdapter, 执行 destroy 方法
      • 先从 dependentBeanMap 里找到所有依赖当前要销毁的 Bean 的 Bean, 为其调用 destroySingleton 优先销毁, 类似依赖注入, 都是递归的
      • 调用 DisposableBeanAdapter 的 destroy 方法, 将各种方法定义的销毁方法都执行掉
  • 清空 dependentBeanMap 和 dependenciesForBeanMap 两个记录了 Bean 的互依赖关系的 Map
  • clearSingletonCache, 清空单例池中剩余的 Bean
  • 清空 manualSingletonNames, 是一个 Set, 存的是用户手动注册的单例 Bean 的 beanName
  • 清空 allBeanNamesByType, 是一个 Map, key 是 bean 类型, value 是该类型所有的 beanName 数组
  • 清空 singletonBeanNamesByType, 和 allBeanNamesByType 类似, 只不过只存了单例 Bean

适配器模式

getBean 的最后一步, 把所有需要执行销毁逻辑的 Bean 都包装成了一个 DisposableBeanAdapter, DisposableBeanAdapter 实现了 DisposableBean 接口, 有 destroy 方法. 定义销毁逻辑的方式有很多, 如实现 DisposableBean 接口, 实现 AutoCloseable 接口, 用 @PreDestroy 注解某个/些方法, 在 BeanDefinition 中指定 destroyMethodName 为具体的某个方法, 在 BeanDefinition 中设置 destroyMethodName 为 (inferred) 且存在 close / shutdown 方法, 在 Bean 被包装为 DisposableBeanAdapter 的时候, 会把根据不同情况调用不同销毁方法的逻辑封装到 DisposableBean 指定的 destroy 方法中, 最后销毁时只需要调用 DisposableBeanAdapter 的 destroy 就可以适配到各种具体的销毁方式

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值