热门标签 | 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启动过程
    本文详细介绍了Spring框架的启动流程,帮助开发者理解其内部机制。通过具体示例和代码片段,解释了Bean定义、工厂类、读取器以及条件评估等关键概念,使读者能够更全面地掌握Spring的初始化过程。 ... [详细]
  • 深入解析SpringMVC核心组件:DispatcherServlet的工作原理
    本文详细探讨了SpringMVC的核心组件——DispatcherServlet的运作机制,旨在帮助有一定Java和Spring基础的开发人员理解HTTP请求是如何被映射到Controller并执行的。文章将解答以下问题:1. HTTP请求如何映射到Controller;2. Controller是如何被执行的。 ... [详细]
  • 本文介绍了如何在多线程环境中实现异步任务的事务控制,确保任务执行的一致性和可靠性。通过使用计数器和异常标记字段,系统能够准确判断所有异步线程的执行结果,并根据结果决定是否回滚或提交事务。 ... [详细]
  • 本文详细介绍了如何在 Android 中使用值动画(ValueAnimator)来动态调整 ImageView 的高度,并探讨了相关的关键属性和方法,包括图片填充后的高度、原始图片高度、动画变化因子以及布局重置等。 ... [详细]
  • docker镜像重启_docker怎么启动镜像dock ... [详细]
  • Python 内存管理机制详解
    本文深入探讨了Python的内存管理机制,涵盖了垃圾回收、引用计数和内存池机制。通过具体示例和专业解释,帮助读者理解Python如何高效地管理和释放内存资源。 ... [详细]
  • 本文介绍如何在Spring Boot项目中集成Redis,并通过具体案例展示其配置和使用方法。包括添加依赖、配置连接信息、自定义序列化方式以及实现仓储接口。 ... [详细]
  • 本文详细介绍了优化DB2数据库性能的多种方法,涵盖统计信息更新、缓冲池调整、日志缓冲区配置、应用程序堆大小设置、排序堆参数调整、代理程序管理、锁机制优化、活动应用程序限制、页清除程序配置、I/O服务器数量设定以及编入组提交数调整等方面。通过这些技术手段,可以显著提升数据库的运行效率和响应速度。 ... [详细]
  • 基于机器学习的人脸识别系统实现
    本文介绍了一种使用机器学习技术构建人脸识别系统的实践案例。通过结合Python编程语言和深度学习框架,详细展示了从数据预处理到模型训练的完整流程,并提供了代码示例。 ... [详细]
  • Redux入门指南
    本文介绍Redux的基本概念和工作原理,帮助初学者理解如何使用Redux管理应用程序的状态。Redux是一个用于JavaScript应用的状态管理库,特别适用于React项目。 ... [详细]
  • CSS高级技巧:动态高亮当前页面导航
    本文介绍了如何使用CSS实现网站导航栏中当前页面的高亮显示,提升用户体验。通过为每个页面的body元素添加特定ID,并结合导航项的类名,可以轻松实现这一功能。 ... [详细]
  • 深入解析 Android IPC 中的 Messenger 机制
    本文详细介绍了 Android 中基于消息传递的进程间通信(IPC)机制——Messenger。通过实例和源码分析,帮助开发者更好地理解和使用这一高效的通信工具。 ... [详细]
  • Spring Boot 中静态资源映射详解
    本文深入探讨了 Spring Boot 如何简化 Web 应用中的静态资源管理,包括默认的静态资源映射规则、WebJars 的使用以及静态首页的处理方法。通过本文,您将了解如何高效地管理和引用静态资源。 ... [详细]
  • SpringMVC RestTemplate的几种请求调用(转)
    SpringMVCRestTemplate的几种请求调用(转),Go语言社区,Golang程序员人脉社 ... [详细]
  • Django Token 认证详解与 HTTP 401、403 状态码的区别
    本文详细介绍了如何在 Django 中配置和使用 Token 认证,并解释了 HTTP 401 和 HTTP 403 状态码的区别。通过具体的代码示例,帮助开发者理解认证机制及权限控制。 ... [详细]
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社区 版权所有