深度解析 Spring 源码:揭秘 AbstractAutowireCapableBeanFactory 的 Bean 生命周期处理

在这里插入图片描述

文章目录

    • 一、AbstractAutowireCapableBeanFactory 概述
      • 1.1 详细分析
      • 1.2 设计思想
    • 二、深入解析AbstractAutowireCapableBeanFactory 的实现细节
      • 2.1 Bean 实例化过程分析
        • 2.1.1 createBean()
        • 2.1.2 createBeanInstance()
      • 2.2 Bean 属性注入的实现机制
        • 2.2.1 populateBean()
        • 2.2.2 applyBeanPropertyValues()
      • 2.3 初始化方法的调用过程
        • 2.3.1 initializeBean()
        • 2.3.2 invokeAwareMethods()
        • 2.3.4 applyBeanPostProcessorsBeforeInitialization()
        • 2.3.5 invokeInitMethods()
        • 2.3.6 applyBeanPostProcessorsAfterInitialization()
      • 2.4 销毁机制的实现
        • 2.4.1 destroyBean()
        • 2.4.2 destroy()
    • 三、实例分析与应用场景
      • 3.1 如何利用 AbstractAutowireCapableBeanFactory 扩展 Bean 的功能
      • 3.2 在项目中如何充分利用 Bean 生命周期处理机制

一、AbstractAutowireCapableBeanFactory 概述

AbstractAutowireCapableBeanFactory是Spring框架中的一个重要类,主要负责实现Bean的自动装配功能。

1.1 详细分析

  1. BeanFactory和AutowireCapableBeanFactory: 在Spring中,BeanFactory是IoC容器的基础接口,负责管理bean的生命周期和依赖注入。AutowireCapableBeanFactoryBeanFactory的子接口,扩展了自动装配功能,可以根据配置自动解析和注入bean的依赖关系。
  2. AbstractAutowireCapableBeanFactory的作用AbstractAutowireCapableBeanFactoryAutowireCapableBeanFactory接口的抽象实现类。它提供了一系列用于自动装配和创建bean的模板方法,包括:
    • 解析bean的依赖关系,根据需要进行自动装配。
    • 执行属性填充,将依赖注入到bean中。
    • 初始化bean,包括调用初始化方法和应用BeanPostProcessors(后置处理器)等。
  3. 关键方法和功能AbstractAutowireCapableBeanFactory中的关键方法包括:
    • createBean(Class beanClass):根据给定的类创建一个新的bean实例。
    • applyBeanPropertyValues(Object existingBean, String beanName):应用属性值到现有的bean实例。
    • initializeBean(Object existingBean, String beanName):初始化bean实例,包括执行初始化方法和应用后置处理器等。
  4. 自动装配:该类实现了自动装配功能,根据bean的依赖关系和配置,自动解析和注入所需的依赖。自动装配可以通过构造函数、设值方法或字段进行。

1.2 设计思想

  1. IoC和 DI: Spring 框架的核心思想之一是 IoC 和 DI。IoC 意味着将控制权交给框架,由框架负责管理对象的生命周期和依赖关系。DI 则是 IoC 的一种具体实现方式,通过依赖注入的方式,将对象的依赖关系从代码中解耦,使得代码更加灵活和可维护。AbstractAutowireCapableBeanFactory 实现了这一设计思想,通过自动装配的方式,实现了对象之间的依赖注入。
  2. 面向接口编程: Spring 框架鼓励面向接口编程,而不是面向实现编程。AbstractAutowireCapableBeanFactory 提供了一系列接口,如 BeanFactory、AutowireCapableBeanFactory 等,通过面向接口编程的方式,提高了代码的可扩展性和灵活性。
  3. 模板方法模式: AbstractAutowireCapableBeanFactory 使用了模板方法模式,定义了一组抽象方法和基本方法,子类可以根据具体需求来实现这些抽象方法,从而实现不同的自动装配策略。
  4. 单一职责原则: 设计思想中的单一职责原则要求一个类应该只有一个引起它变化的原因。AbstractAutowireCapableBeanFactory 的设计遵循了这一原则,它专注于实现 Bean 的自动装配功能,而将其他功能如 Bean 的创建、初始化等交给了父类 AbstractBeanFactory 来实现,从而使得类的职责更加清晰和单一。

二、深入解析AbstractAutowireCapableBeanFactory 的实现细节

本文主要详解Bean生命周期的核心实现方法,过程有些缺少,想要了解的Bean生命周期全过程的读者,可以查看我上一篇文章。

2.1 Bean 实例化过程分析

2.1.1 createBean()

根据提供的类信息和配置创建一个新的 Bean 实例,并将其作用域设置为原型模式。

在这里插入图片描述

主要负责 Bean 实例的创建过程,包括解析类信息、准备方法覆盖、实例化前的处理以及实际的 Bean 创建过程。

在这里插入图片描述

2.1.2 createBeanInstance()

主要负责创建 Bean 实例,体现Spring在实例化Bean时考虑的各种情况,包括是否需要自动装配,构造方法是否已经解析,以及如何选择合适的构造方法来创建Bean实例

在这里插入图片描述

2.2 Bean 属性注入的实现机制

2.2.1 populateBean()

主要负责填充Bean属性的populateBean方法,负责处理Bean的属性值,包括自动装配和依赖检查。

在这里插入图片描述

在这里插入图片描述

2.2.2 applyBeanPropertyValues()

主要用于将Bean定义中的属性值应用到已存在的Bean实例上的方法。

在这里插入图片描述

2.3 初始化方法的调用过程

2.3.1 initializeBean()

负责初始化Bean,调用Bean生命周期中的回调方法,包括Aware接口方法和自定义的初始化方法。

在这里插入图片描述

2.3.2 invokeAwareMethods()

确保了实现了Aware接口的Bean,可以在其生命周期中获得对Spring容器的相关信息的访问。

在这里插入图片描述

2.3.4 applyBeanPostProcessorsBeforeInitialization()

确保了在Bean初始化之前,所有的Bean后处理器都有机会对Bean进行自定义操作。

在这里插入图片描述

2.3.5 invokeInitMethods()

确保了Bean在初始化过程中可以执行自定义的逻辑,包括实现InitializingBean接口的Bean的afterPropertiesSet方法和Bean定义中指定的自定义初始化方法。

在这里插入图片描述

2.3.6 applyBeanPostProcessorsAfterInitialization()

确保了在Bean初始化之后,所有的Bean后处理器都有机会对Bean进行自定义操作。

在这里插入图片描述

2.4 销毁机制的实现

2.4.1 destroyBean()

确保了Bean在销毁过程中可以执行自定义的逻辑,包括实现DisposableBean接口的Bean的destroy方法和Bean定义中指定的自定义销毁方法。

在这里插入图片描述

2.4.2 destroy()

负责调用实现了DisposableBean接口的Bean的destroy方法,以及Bean定义中指定的自定义销毁方法。

在这里插入图片描述

在这里插入图片描述

三、实例分析与应用场景

3.1 如何利用 AbstractAutowireCapableBeanFactory 扩展 Bean 的功能

要利用AbstractAutowireCapableBeanFactory扩展Bean的功能,可以通过编写自定义的BeanPostProcessorBeanFactoryPostProcessor来实现。这两个接口允许在Spring容器实例化和配置Bean的不同阶段介入并添加自定义逻辑。例如,可以在Bean初始化前后执行额外的操作,或者在Bean实例化前修改Bean的定义。

使用BeanPostProcessor来扩展Bean功能的Demo:

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

/** 
 * CustomBeanPostProcessor实现了BeanPostProcessor接口,并覆盖了postProcessBeforeInitialization和postProcessAfterInitialization方法
 * 这两个方法分别在Bean初始化之前和之后执行
 * 可以在这些方法中添加自定义的逻辑,以扩展Bean的功能
 */
@Component
public class CustomBeanPostProcessor implements BeanPostProcessor {

    /**
     * 日常开发中:可以执行额外的初始化操作,例如初始化某些属性、连接到外部资源或设置日志记录器等
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        // 在Bean初始化之前执行操作
        if (bean instanceof CustomBean) {
            ((CustomBean) bean).beforeInit(); // 假设CustomBean有一个beforeInit方法
        }
        return bean;
    }

    /**
     * 日常开发中:可以执行额外的销毁操作,例如释放资源、关闭连接或记录统计信息等
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        // 在Bean初始化之后执行操作
        if (bean instanceof CustomBean) {
            ((CustomBean) bean).afterInit(); // 假设CustomBean有一个afterInit方法
        }
        return bean;
    }
}

使用BeanFactoryPostProcessor扩展Bean功能的Demo

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;

/**
 * CustomBeanFactoryPostProcessor实现了BeanFactoryPostProcessor接口
 * 在postProcessBeanFactory方法中注册了一个名为"customBean"的新Bean
 */
@Component
public class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

     /**
     * 日常开发中:修改Bean定义等
     */
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        // 在这里可以访问和修改Bean的定义
        
        // 如:添加一个新的Bean定义
        beanFactory.registerSingleton("customBean", new CustomBean());
    }
}

3.2 在项目中如何充分利用 Bean 生命周期处理机制

案例:有一个简单的Spring Boot项目,其中包含一个名为UserService的服务类,以及一个名为CustomBean的自定义Bean类。将通过自定义初始化和销毁逻辑、AOP、事件监听器和与外部资源的连接来展示如何充分利用Bean生命周期处理机制。

CustomBean自定义Bean类:

import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

/**
 * 演示自定义初始化和销毁逻辑
 */
@Component
public class CustomBean {

    @PostConstruct
    public void init() {
        System.out.println("CustomBean initialized");
        // 添加自定义的初始化逻辑...
    }

    @PreDestroy
    public void destroy() {
        System.out.println("CustomBean destroyed");
        // 添加自定义的销毁逻辑...
    }
}

CustomBeanPostProcessor类:

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

/**
 * 实现BeanPostProcessor接口,以便在Bean的初始化和销毁阶段添加自定义逻辑
 */
@Component
public class CustomBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof CustomBean) {
            ((CustomBean) bean).init();
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof CustomBean) {
            ((CustomBean) bean).destroy();
        }
        return bean;
    }
}

CustomAspect切面类:

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class CustomAspect {

    @After("execution(* com.example.UserService.*(..))")
    public void afterUserServiceMethods() {
        System.out.println("AOP: After UserService methods");
        // 添加横切关注点...
    }
}

CustomApplicationListener类:

import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;

/**
 * 实现ApplicationListener接口,以便监听Bean生命周期事件
 */
@Component
public class CustomApplicationListener implements ApplicationListener<ContextRefreshedEvent> {

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        System.out.println("ApplicationListener: Context refreshed");
        // 监听器逻辑...
    }
}

UserService中使用外部资源(例如数据库连接)

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

@Service
public class UserService {

    @Autowired
    private DataSource dataSource;

    @PostConstruct
    public void init() {
        System.out.println("UserService initialized");
        // 连接到外部资源...
    }

    public void createUser(String username) {
        System.out.println("Creating user: " + username);
        // 业务逻辑...
    }

    public void deleteUser(String username) {
        System.out.println("Deleting user: " + username);
        // 业务逻辑...
    }

    @PreDestroy
    public void destroy() {
        System.out.println("UserService destroyed");
        // 释放外部资源...
    }
}

山的那边有我的期许,你有看见吗

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/603179.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

560. 和为 K 的子数组 974. 和可被 K 整除的子数组 【前缀和】

题目链接 ​​​​​​​974. 和可被 K 整除的子数组 560. 和为 K 的子数组 今天刷题的时候&#xff0c;刷了这两题&#xff0c;感觉挺有意思的。代码写起来挺简单的&#xff0c;但是思路和其中的细节以及涉及到的知识点确实让我挺意外的。这里写个博客解析一波&#xff0c;也是…

Charles抓包工具

Charles是一个HTTP代理工具&#xff0c;使开发人员能够查看客服端和服务器之间的所有HTTP/ HTTPS/SSL网络请求。 Charles是在PC环境下常用的网络抓包截取工具&#xff0c;在做移动开发时&#xff0c;我们为了调试客户端与服务端的网络通讯协议&#xff0c;常常需要截取网络请求…

MCP3008-I/SL 模数转换器ADC SPI接口 模拟信号采集

MCP3008-I/SL 模数转换器ADC 贴片SOIC16 MCP3008-I/SL 是一款模数转换器&#xff08;ADC&#xff09;&#xff0c;属于 SAR&#xff08;逐次逼近寄存器&#xff09;架构的 ADC。它具有以下特点&#xff1a; 8 通道单 ADC 最大采样率&#xff1a;200ksps&#xff08;千样点每秒…

鸿蒙内核源码分析(编译环境篇) | 编译鸿蒙防掉坑指南

几点说明 kernel_liteos_a_note | 中文注解鸿蒙内核 是在 OpenHarmony 的 kernel_liteos_a 基础上给内核源码加上中文注解的版本.与官方源码按月保持同步,同步历史如下: 2021/10/09 – 增加性能优化模块perf,优化了文件映射模块2021/09/14 – common,extended等几个目录结构和M…

文献速递:深度学习医学影像心脏疾病检测与诊断--基于深度学习的低剂量SPECT心肌灌注图像去噪:定量评估与临床表现

Title 题目 Deep learning–based denoising of low‑dose SPECT myocardialperfusion images: quantitative assessment and clinical performance 基于深度学习的低剂量SPECT心肌灌注图像去噪&#xff1a;定量评估与临床表现 01 文献速递介绍 单光子发射计算机断层扫描&a…

uniapp + vue3 设置 axios proxy 代理,并重写路径

uniapp vue2 设置代理如下&#xff1a; 已生成的项目架构里面找到manifest.json文件&#xff0c;通过源码视图的方式打开文件&#xff0c;在文件中添加一下代码即可完成代理&#xff1a; "h5": {"devServer": {"disableHostCheck": true, //禁…

基于StatefulSet控制器在Kubernetes上部署MySQL一主多从

一、前提--StatefuSet特性 1.1 有状态的节点控制器 -- StatefulSet 及其网络状态 容器的解决方案是针对无状态应用场景的最佳实践&#xff0c;但对于有状态应用来说&#xff0c;就并非如此了。Kubernetes 用 StatefulSet 解决了有状态应用编排的问题&#xff0c;本文我们就来…

GitHub介绍,GitHub如何订阅充值?

一、GitHub介绍 GitHub是一个面向开源及私有软件项目的托管平台&#xff0c;因为只支持git 作为唯一的版本库格式进行托管&#xff0c;故名Github。 GitHub于2008年4月10日正式上线&#xff0c;除了git代码仓库托管及基本的Web管理界面以外&#xff0c;还提供了订阅、讨论组、…

爬取深圳2024年链家二手房数据,共3000条数据(其他城市也可)

文章目录 专栏导读1.目标2.导入相关库3.获取每个二手房的链接4.获取每个链接中的相关数据5.保存数据6.数据展示 专栏导读 ✍ 作者简介&#xff1a;i阿极&#xff0c;CSDN 数据分析领域优质创作者&#xff0c;专注于分享python数据分析领域知识。 ✍ 本文录入于《python网络爬虫…

探索数据结构

什么是数据结构 数据结构是由&#xff1a;“数据”与“结构”两部分组成 数据与结构 数据&#xff1a;如我们所看见的广告、图片、视频等&#xff0c;常见的数值&#xff0c;教务系统里的&#xff08;姓名、性别、学号、学历等等&#xff09;&#xff1b; 结构&#xff1a;当…

Pandas进阶

文章目录 第1关&#xff1a;Pandas 分组聚合第2关&#xff1a;Pandas 创建透视表和交叉表 第1关&#xff1a;Pandas 分组聚合 编程要求 使用 Pandas 中的 read_csv() 函数读取 step1/drinks.csv 中的数据&#xff0c;数据的列名如下表所示&#xff0c;请根据 continent 分组并…

VMware 虚拟机自定义规范 - 更优雅的虚拟机开局

介绍 虚拟机自定义规范可以在你克隆虚拟机的时候在vCenter 的Web界面设定虚拟机的主机名、单/多网卡IP的IP和网关、DNS服务器、唯一标识符重置&#xff08;SID等&#xff09;、硬盘分区自动扩容、设定密码、密钥、时区等信息。 让管理员不需要进入虚拟机系统内部进行配置&…

10000字讲解IoC 思想以及五大注解

文章目录 IoC 思想通过案例讲解 IoC1.传统的开发方式 SpringIoC 和 DI五大注解ControllerServiceComponentRepositoryConfiguration 为什么要有这么多的类注解类注解之间的关系方法注解 Bean重命名 bean扫描路径 IoC 思想 什么是 Spring 呢&#xff1f; 我们经常听到的都是说…

Android 13 aosp 默认关闭SELinux

通过adb修改 adb root adb shell setenforce 0 // 开SELinux&#xff0c;设置成模式permissive adb shell setenforce 1 // 关SELinux&#xff0c;设置成模式enforce adb shell getenforce // 获取当前SELinux状态源码修改 Android_source/system/core/init/selinu…

JS-导入导出

export和export default是ES6中导出模块中变量的语法 导入导出变量 //导出方法&#xff08;js文件中&#xff09; export const 变量名值//导入方法 对应导入的变量&#xff0c;一定要加花括号 import {变量名} from js文件路径 导入导出函数 //导出方法&#xff08;js文件中…

2024.1IDEA 到2026年

链接&#xff1a;https://pan.baidu.com/s/1hjJEV5A5k1Z9JbPyBXywSw?pwd9g4i 提取码&#xff1a;9g4i解压之后,按照 操作说明.txt 操作; IntelliJ IDEA 2024.1 (Ultimate Edition) Build #IU-241.14494.240, built on March 28, 2024 Licensed to gurgles tumbles You have…

福汇美股开户教程

福汇作为全球知名的外汇交易平台&#xff0c;也提供美股交易服务。在福汇交易美股&#xff0c;首先需要开立一个福汇账户。本教程将详细介绍福汇美股开户流程。 第一步&#xff1a;访问福汇官网并填写开户表格 访问福汇美股入口点击页面顶部的“开户”按钮。选择您的国籍&…

JetsonNano —— Windows下对Nano板卡烧录刷机(官方教程)

介绍 NVIDIA Jetson Nano™ 开发者套件是一款面向创客、学习者和开发人员的小型 AI 计算机。按照这个简短的指南&#xff0c;你就可以开始构建实用的 AI 应用程序、酷炫的 AI 机器人等了。 烧录刷机 1、下载 Jetson Nano开发者套件SD卡映像&#xff0c;并记下它在计算机上的保存…

初探MFC程序混合使用QT

一、背景 随着操作系统国产化替代的趋势越发明显&#xff0c;软件支持国际化、跨平台&#xff0c;已然是必须做的一件事情。原有的软件UI层用的是MFC&#xff0c;将其换成QT&#xff0c;想必是一种较好的方案。对于大型软件&#xff0c;特别是已发布&#xff0c;但还处于不断迭…

vue 开发环境的搭建

一、整个流程&#xff1a; 安装nodejs >> 安装vue >> 安装vue-cli >> 初始化 webpack(生成代码) >> 安装依赖 >> 运行vue程序 二、详细安装流程&#xff1a; 1.安装nodejs 下载&#xff1a;https://nodejs.org/dist/v12.18.3/node-v12.18.3-x…
最新文章