热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Spring源码分析之Bean生命周期

前言Spring中一个Bean的创建过程是十分复杂的,这里通过源码来简单分析一下。原理分析相关类图如下DefaultListableBeanFactory就是IOC容器的最终实现,

前言

Spring中一个Bean的创建过程是十分复杂的,这里通过源码来简单分析一下。


原理分析

相关类图如下

DefaultListableBeanFactory就是IOC容器的最终实现,既实现了BeanFactory接口,也实现了BeanDefinitionRegistry接口,

所以它不仅是Bean容器,也是BeanDefinition注册表,同时管理Bean和BeanDefinition,接下来就来分析一下DefaultListableBeanFactory是如何创建Bean的。

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
public class TestBeanFactory {
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
BeanDefinitionBuilder definitiOnBuilder= BeanDefinitionBuilder
.genericBeanDefinition(UserService.class);
definitionBuilder.addPropertyValue("username", "lisi");
beanFactory.registerBeanDefinition("userService", definitionBuilder.getBeanDefinition());
UserService userService = (UserService) beanFactory.getBean("userService");
System.out.println(userService.getUsername());
}
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class UserService {
private String username;
}
}

我们先自己注册了UserService的BeanDefinition(项目中一般都是通过扫描自动注册的),核心方法就是beanFactory.getBean(beanName),接下来就深入到方法内部来看一下。

首先进入AbstractBeanFactory内部。

protected T doGetBean(final String name, @Nullable final Class requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
//处理FactoryBean类型的Bean名称,暂时不管
final String beanName = transformedBeanName(name);
Object bean;
//查看是否已经创建过(从单例池中查询)
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
//也是处理FactoryBean相关
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
try {
//上面已经说了,DefaultListableBeanFactory也实现了BeanDefinitionRegistry,所以也管理BeanDefinition,这里根据Bean名称查询出之前注册的BeanDefinition
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
//处理依赖Bean,项目中一般也用不到
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
//依次创建依赖Bean
getBean(dep);
}
}
//创建单例Bean
if (mbd.isSingleton()) {
//创建完成之后会将Bean放到单例池中,下次直接从池中取就可以了
sharedInstance = getSingleton(beanName, () -> {
try {
//真正创建Bean的地方
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
//销毁Bean
destroySingleton(beanName);
throw ex;
}
});
//处理FactoryBean相关
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
//创建原型Bean(每次都会创建),暂时不管
else if (mbd.isPrototype()) {

}
else {
//处理其他scope的Bean,如web环境下的request类型的scope,暂时不管
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
//检查Bean类型和我们要求的类型是否一致,进行类型转换
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
T cOnvertedBean= getTypeConverter().convertIfNecessary(bean, requiredType);
return convertedBean;
}

}
return (T) bean;
}

除去非必要的代码,最终创建Bean的核心方法为createBean(),这个方法是通过AbstractAutowireCapableBeanFactory实现的,继续跟进去

@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
RootBeanDefinition mbdToUse = mbd;
//解析出Bean的Class类型
Class resolvedClass = resolveBeanClass(mbd, beanName);

try {
//这里给BeanPostProcessors一个机会使用一个代理对象来代替目标Bean实例,关于BeanPostProcessor,下面介绍
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
try {
//实际创建Bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
}

继续doCreateBean()方法

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
//创建Bean实例
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
//也是处理FactoryBean相关
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//创建Bean实例,会找到最合适的构造器,通过反射创建对象
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
Class beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
//允许BeanPostProcessor修改BeanDefinition,暂时不管
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
mbd.postProcessed = true;
}
}
//解决循环依赖相关
boolean earlySingletOnExposure= (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
//初始化Bean实例
Object exposedObject = bean;
try {
//Bean属性装配,AutowiredAnnotationBeanPostProcessor就是在这里被调用来处理@Autowired和@Value注解的
populateBean(beanName, mbd, instanceWrapper);
//初始化Bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
return exposedObject;
}

继续初始化Bean过程

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
//处理一些钩子方法的回调,如果当前Bean实现了BeanFactoryAware接口,就会调用当前Bean的setBeanFactory()方法
invokeAwareMethods(beanName, bean);
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//调用BeanPostProcessor的postProcessBeforeInitialization(),可以让我们在Bean初始化之前做一些事情,是Spring提供的一个扩展
//ApplicationContextAwareProcessor在这一步会处理更多的钩子方法的回调
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
//调用我们定义的初始化方法,如果实现了InitializingBean接口,就调用afterPropertiesSet()方法,如果还配置了自定义初始化方法,也调用
//@Bean注解可以使用initMethod属性来配置
invokeInitMethods(beanName, wrappedBean, mbd);
}
if (mbd == null || !mbd.isSynthetic()) {
//调用BeanPostProcessor的postProcessAfterInitialization(),可以让我们在Bean初始化之后做一些事情,也是Spring提供的一个扩展
//AOP创建代理对象就是通过AnnotationAwareAspectJAutoProxyCreator扩展此功能实现的
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}

BeanFactory提供了addBeanPostProcessor()方法来添加我们自定义的BeanPostProcessor对象,如果使用ApplicationContext,就不需要手动添加了,我们只需要将它标记为一个Bean,ApplicationContext会自动去IOC容器中查找所有类型为BeanPostProcessor的Bean,调用addBeanPostProcessor()方法将它们添加到BeanFactory中。

@Component
public static class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
System.out.println("postProcessAfterInitialization: " + beanName);
return bean;
}
}

IOC容器底层是使用一个ConcurrentHashMap来保存Bean名称和Bean实例对象的对应关系的,DefaultListableBeanFactory是DefaultSingletonBeanRegistry的一个子类。


总结

Bean生命周期基本如下


参考

Spring IOC 容器源码分析



推荐阅读
  • Spring – Bean Life Cycle
    Spring – Bean Life Cycle ... [详细]
  • MySQL初级篇——字符串、日期时间、流程控制函数的相关应用
    文章目录:1.字符串函数2.日期时间函数2.1获取日期时间2.2日期与时间戳的转换2.3获取年月日、时分秒、星期数、天数等函数2.4时间和秒钟的转换2. ... [详细]
  • 一、Tomcat安装后本身提供了一个server,端口配置默认是8080,对应目录为:..\Tomcat8.0\webapps二、Tomcat8.0配置多个端口,其实也就是给T ... [详细]
  • 在 CentOS 7 环境中使用 MySQL 5.6 镜像启动数据库时遇到权限问题,本文将详细探讨并提供解决方案。 ... [详细]
  • Spring Data JdbcTemplate 入门指南
    本文将介绍如何使用 Spring JdbcTemplate 进行数据库操作,包括查询和插入数据。我们将通过一个学生表的示例来演示具体步骤。 ... [详细]
  • 本文介绍了Spring 2.0引入的TaskExecutor接口及其多种实现,包括同步和异步执行任务的方式。文章详细解释了如何在Spring应用中配置和使用这些线程池实现,以提高应用的性能和可管理性。 ... [详细]
  • 为什么多数程序员难以成为架构师?
    探讨80%的程序员为何难以晋升为架构师,涉及技术深度、经验积累和综合能力等方面。本文将详细解析Tomcat的配置和服务组件,帮助读者理解其内部机制。 ... [详细]
  • Hadoop的文件操作位于包org.apache.hadoop.fs里面,能够进行新建、删除、修改等操作。比较重要的几个类:(1)Configurati ... [详细]
  • 如果应用程序经常播放密集、急促而又短暂的音效(如游戏音效)那么使用MediaPlayer显得有些不太适合了。因为MediaPlayer存在如下缺点:1)延时时间较长,且资源占用率高 ... [详细]
  • ECharts 官方提供了丰富的图表示例,但实际项目中往往需要从后端动态获取数据。本文将详细介绍如何从后端获取数据并将其转换为 ECharts 所需的 JSON 格式,以实现动态饼图的展示。 ... [详细]
  • 本文将带你快速了解 SpringMVC 框架的基本使用方法,通过实现一个简单的 Controller 并在浏览器中访问,展示 SpringMVC 的强大与简便。 ... [详细]
  • 本文介绍了在 Java 编程中遇到的一个常见错误:对象无法转换为 long 类型,并提供了详细的解决方案。 ... [详细]
  • 本教程详细介绍了如何使用 Spring Boot 创建一个简单的 Hello World 应用程序。适合初学者快速上手。 ... [详细]
  • javascript分页类支持页码格式
    前端时间因为项目需要,要对一个产品下所有的附属图片进行分页显示,没考虑ajax一张张请求,所以干脆一次性全部把图片out,然 ... [详细]
  • Python 3 Scrapy 框架执行流程详解
    本文详细介绍了如何在 Python 3 环境下安装和使用 Scrapy 框架,包括常用命令和执行流程。Scrapy 是一个强大的 Web 抓取框架,适用于数据挖掘、监控和自动化测试等多种场景。 ... [详细]
author-avatar
TXCWB_523
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有