0-前置知识

前言

SpringBoot框架在设计之初,为了有更好的兼容性,在不同的运行阶,段提供了非常多的扩展点,可以让程序员根据自己的需求,在整个Spring应用程序运行过程中执行程序员自定义的代码。

ApplicationContextInitializer

IOC容器创建完之后执行,可以对上下文环境做一些操作,例如运行环境属性注册等

使用

  1. 自定义类,实现ApplicationContextInitializer接口
  2. 在META-INF/spring.factories配置文件中配置自定义的类

示例

自定义类

public class MyApplicationContextInitializer implements ApplicationContextInitializer {
    // ioc容器对象创建完毕后执行
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        // 给上下文context对象注入环境属性
        // 1.准备属性
        Map<String, Object> myMap = new HashMap<>();
        myMap.put("applicationName", "lxx666");

        // 2.获取属性资源管理对象
        // 获取环境对象
        ConfigurableEnvironment environment = applicationContext.getEnvironment();
        // 属性资源管理对象
        MutablePropertySources propertySources = environment.getPropertySources();

        // 3.注册
        propertySources.addLast(new MapPropertySource("myMap",myMap));
    }
}

配置自定义的类,位置:src/main/resources/META-INF/spring.factories

# 接口全路径名称=自定义类全路径名称
org.springframework.context.ApplicationContextInitializer = com.lxx.Initializer.MyApplicationContextInitializer

测试

@SpringBootApplication
public class SpringbootInterviewApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(SpringbootInterviewApplication.class, args);
        String applicationName = context.getEnvironment().getProperty("applicationName");
        System.out.println(applicationName);
    }

}

结果

lxx666

ApplicationListener

监听容器发布的事件,运行程序员执行自己的代码,完成事件驱动开发,它可以监听容器初始化完成,初始化失败等事件,通常情况下可以使用监听器加载资源,开启定时任务等

使用

  1. 自定义类,实现ApplicationListener接口
  2. 在META-INF/spring.factories配置文件中配置自定义的类

示例

自定义类

public class MyApplicationListener implements ApplicationListener {
    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        // ApplicationEvent event 对应的就是发布的事件,ApplicationReadyEvent,ApplicationFailedEvent
        if (event instanceof ApplicationReadyEvent) {
            // 容器初始化成功
            System.out.println("MyApplicationListener...容器初始化成功...");
        }
        if (event instanceof ApplicationFailedEvent) {
            // 容器初始化成功
            System.out.println("MyApplicationListener...容器初始化失败...");
        }
    }
}

配置自定义的类,位置:src/main/resources/META-INF/spring.factories

org.springframework.context.ApplicationListener = com.lxx.listener.MyApplicationListener

测试

@SpringBootApplication
public class SpringbootInterviewApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(SpringbootInterviewApplication.class, args);
    }

}

结果

MyApplicationListener...容器初始化成功...

BeanFactory

Bean容器的根接口,提供Bean对象的创建、配置、依赖注入等功能

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

AnnotationConfigServletWebServerApplicationContext -> DefaultListableBeanFactory

在这里插入图片描述

最终得到的容器类型AnnotationConfigServletWebServerApplicationContext

在这里插入图片描述

调用容器的getBean()时,底层是调用了DefaultListableBeanFactory的getBean()。

@SpringBootApplication
public class SpringbootInterviewApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(SpringbootInterviewApplication.class, args);
        context.getBean(SpringbootInterviewApplication.class);
    }

}

在这里插入图片描述

它们之间存在一种委托关系

在这里插入图片描述

BeanDefinition

用于描述Bean,包括Bean的名称,Bean的属性,Bean的行为,实现的接口,添加的注解等等。Spring中,Bean在创建之前,都需要封装成对应的BeanDefinition,然后根据BeanDefinition进一步创建Bean对象

在这里插入图片描述

在这里插入图片描述

示例

// Bean对应的信息会封装到ScannedGenericBeanDefinition
@Component
public class Student {

}
// Bean对应的信息会封装到ConfigurationClassBeanDefinition
@Configuration
public class MyConfig {

    @Bean
    public String aa() {
        return "lxx666";
    }
}
@SpringBootApplication
public class SpringbootInterviewApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(SpringbootInterviewApplication.class, args);
        // 获取BeanDefinition对象
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        BeanDefinition stuBdf = beanFactory.getBeanDefinition("student");
        BeanDefinition aaBdf = beanFactory.getBeanDefinition("aa");
        System.out.println(stuBdf.getClass());
        System.out.println(aaBdf.getClass());
    }

}

结果

class org.springframework.context.annotation.ScannedGenericBeanDefinition
class org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader$ConfigurationClassBeanDefinition

BeanFactoryPostProcessor

Bean工厂后置处理器,当BeanFactory准备好之后(Bean初始化之前)会调用该接口的postProcessBeanFactory方法,经常用于新增BeanDefinition

SpringBoot内置的BeanFactoryPostProcessor

实现类名作用
ConfigurationClassPostProcessor扫描启动类所在包下的注解
ServletComponentRegisteringPostProcessor扫描@WebServlet、@WebFilter、@WebListener
CachingMetadataReaderFactoryPostProcessor配置ConfigurationClassPostProcessor
ConfigurationWarningsPostProcessor配置警告提示

示例

public class Teacher {
}
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    // 当BeanFactory实例化好之后(bean创建之前),回调这个函数,注册一些BeanDefinition
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        // 注册一个Teacher的BeanDefinition
        GenericBeanDefinition gbdf = new GenericBeanDefinition();
        gbdf.setBeanClass(Teacher.class);
        // 向下强转
        DefaultListableBeanFactory dbf = (DefaultListableBeanFactory) beanFactory;
        // 注册
        dbf.registerBeanDefinition("teacher", gbdf);

    }
}
@SpringBootApplication
public class SpringbootInterviewApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(SpringbootInterviewApplication.class, args);
        Object teacher = context.getBean("teacher");
        System.out.println(teacher);
    }

}

结果

com.lxx.processor.Teacher@43982337

Aware

感知接口,Spring提供的一种机制,通过实现该接口,重写方法,可以感知Spring应用程序执行过程中的一些变化。Spring会判断当前的Bean有没有实现Aware接口,如果实现了,会在特定的时机回调接口中对应的方法

子接口名作用
BeanNameAwareBean名称的感知接口
BeanClassLoaderAwareBean类加载器的感知接口
BeanFactoryAwareBean工厂的感知接口

实例

@Component
public class Lxx implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware {
    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        System.out.println("lxx...setBeanClassLoader..." + classLoader);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("lxx...setBeanFactory..." + beanFactory);
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("lxx...setBeanName..." + name);
    }
}

结果

lxx...setBeanName...lxx
lxx...setBeanClassLoader...jdk.internal.loader.ClassLoaders$AppClassLoader@63947c6b
lxx...setBeanFactory...org.springframework.beans.factory.support.DefaultListableBeanFactory@38f116f6

InitializingBean/DisposableBean

初始化接口,当Bean被实例化好后,会回调里面的函数,经常用于做一些加载资源的工作

销毁接口,当Bean被销毁之前,会回调里面的函数,经常用于做一些释放资源的工作

实例

@Component
public class Animal implements InitializingBean, DisposableBean {
    // 销毁方法
    @Override
    public void destroy() throws Exception {
        System.out.println("Animal...destroy");
    }

    // 初始化方法
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("Animal...afterPropertiesSet");
    }

    // @PostConstruct @PreDestroy 注解提供初始化和销毁方法

}

BeanPostProcessor

Bean的后置处理器,当Bean对象初始化之前以及初始化之后,会回调该接口对应的方法

  • postProcessBeforeInitialization:Bean对象初始化之前调用
  • postProcessAfterInitialization:Bean对象初始化之后调用

SpringBoot内置的BeanPostProcessor

实现类名作用
AutowiredAnnotationBeanPostProcessor用来完成依赖注入
AbstractAutoProxyCreator用来完成代理对象的创建
AbstractAdvisingBeanPostProcessor将aop中的通知作用于特定的bean上

示例

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    // Bean对象初始化之前调用
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("MyBeanPostProcessor...postProcessBeforeInitialization..."+beanName);
        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }

    // Bean对象初始化之后调用
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("MyBeanPostProcessor...postProcessAfterInitialization..."+beanName);
        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }
}

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

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

相关文章

springcloud-网关(gateway)

springcloud-网关(gateway) 概述 \Spring Cloud Gateway旨在提供一种简单而有效的方式来路由到API&#xff0c;并为其提供跨领域的关注&#xff0c;如&#xff1a;安全、监控/指标和容错 常用术语 Route&#xff08;路由&#xff09;: 网关的基本构件。它由一个ID、一个目的地…

软考 系统分析师系列知识点之企业信息化规划(1)

所属章节&#xff1a; 第7章. 企业信息化战略与实施 第2节. 企业信息化规划 企业信息化建设是一项长期而艰巨的任务&#xff0c;不可能在短时间内完成。因此&#xff0c;企业信息化建设必然会分解成各个相对独立的项目&#xff0c;在不同时期分别实施&#xff0c;从而建立多个…

1902_野火FreeRTOS教程内核在STM32中用到的2个中断PENDSV和SYSTICK

1902_野火FreeRTOS教程内核在STM32中用到的2个中断PENDSV和SYSTICK 全部学习汇总&#xff1a; g_FreeRTOS: FreeRTOS学习笔记 (gitee.com) 上面是涉及到的源代码&#xff0c;而这次需要分析的就是78、79行的两个中断。首先&#xff0c;需要确认NVIC_SYSPRI2寄存器的作用。 进一…

jquery写组件滑动人机验证组件

jquery组件&#xff0c;虽然 jquery 语法古老&#xff0c;但是写好了用起来真的很爽啊&#xff0c;本文用滑动人机验证给大家做个详细教程&#xff08;直接复制代码就可以用噢o(*&#xffe3;▽&#xffe3;*)ブ&#xff09; 第一步 先看下组件本身 component.js (function() {…

QT中的多线程有什么作用?

概述 在学习QT线程的时候我们首先要知道的是QT的主线程&#xff0c;也叫GUI线程&#xff0c;意如其名&#xff0c;也就是我们程序的最主要的一个线程&#xff0c;主要负责初始化界面并监听事件循环&#xff0c;并根据事件处理做出界面上的反馈。但是当我们只限于在一个主线程上…

Python urllib模块学习

HTTP协议 HTTP 协议&#xff1a;一般指HTTP(超文本传输)协议。 HTTP是为Web浏览器和Web服务器之间的通信而设计的&#xff0c;基于TCP/IP通信协议嘞传递数据。 HTTP消息结构 客户端请求消息 客户端发送一个HTTP请求到服务器的请求消息包括以下格式 请求行(request line)请求…

基于Java开发的个人视频网站的搭建与实现[附源码]

基于Java开发的个人视频网站的搭建与实现[附源码] &#x1f345; 作者主页 央顺技术团队 &#x1f345; 欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; &#x1f345; 文末获取源码联系方式 &#x1f4dd; &#x1f345; 查看下方微信号获取联系方式 承接各种定制系统 &am…

威来国际教育:留学服务的全新标杆,打造无忧留学体验

在当今全球化日益加深的背景下&#xff0c;留学已成为众多年轻人拓宽视野、提升个人能力的重要手段。随着留学市场的不断扩大和留学目的地的多样化&#xff0c;家庭和学生在选择留学服务时更加注重专业性和全面性。 在这一领域&#xff0c;威来国际教育凭借其深厚的背景和专业的…

mysql 2-20

TEXT类型 枚举类型 SET类型 二进制字符串类型 BLOB类型 注意事项 JSON类型 提取数据 空间类型 选择建议 约束

Spark 离线开发框架设计与实现

一、背景 随着 Spark 以及其社区的不断发展&#xff0c;Spark 本身技术也在不断成熟&#xff0c;Spark 在技术架构和性能上的优势越来越明显&#xff0c;目前大多数公司在大数据处理中都倾向使用 Spark。Spark 支持多种语言的开发&#xff0c;如 Scala、Java、Sql、Python 等。…

创业者看到这3000多箱磁吸春联滞销面临销毁一定要吸取教训!

2月18日&#xff0c;浙江金华一个工厂&#x1f3ed;3000多箱龙年磁吸春联&#xff0c; 因为滞销&#xff0c;加上春联中含有龙元素和日期而面临报废销毁&#xff0c; 造成了数十万的损失以及大量的资源浪费。 —————————— 而引起广泛的社会讨论&#x1f5e3;️&…

《Solidity 简易速速上手小册》第8章:高级 Solidity 概念(2024 最新版)

文章目录 8.1 高级数据类型和结构8.1.1 基础知识解析更深入的理解实际操作技巧 8.1.2 重点案例&#xff1a;构建一个去中心化身份系统案例 Demo&#xff1a;创建去中心化身份系统案例代码DecentralizedIdentityContract.sol 测试和验证拓展案例 8.1.3 拓展案例 1&#xff1a;管…

C++力扣题目 121--买卖股票的最佳时机 122-- 买卖股票的最佳时机II 123--买卖股票的最佳时机III 188--买卖股票的最佳时机IV

121. 买卖股票的最佳时机 力扣题目链接(opens new window) 给定一个数组 prices &#xff0c;它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票&#xff0c;并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所…

基于FPGA的二维DCT变换和逆变换verilog实现,包含testbench

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 数据导入到matlab显示图像 2.算法运行软件版本 vivado2019.2 matlab2022a 3.部分核心程序 timescale 1ns / 1ps // // Company: // Engineer:…

阿里云国际-在阿里云服务器上快速搭建幻兽帕鲁多人服务器

幻兽帕鲁是最近流行的新型生存游戏。该游戏一夜之间变得极为流行&#xff0c;同时在线玩家数量达到了200万。然而&#xff0c;幻兽帕鲁的服务器难以应对大量玩家的压力。为解决这一问题&#xff0c;幻兽帕鲁允许玩家建立专用服务器&#xff0c;其提供以下优势&#xff1a; &am…

如何在Ubuntu部署Emlog,并将本地博客发布至公网可远程访问

文章目录 前言1. 网站搭建1.1 Emolog网页下载和安装1.2 网页测试1.3 cpolar的安装和注册 2. 本地网页发布2.1 Cpolar临时数据隧道2.2.Cpolar稳定隧道&#xff08;云端设置&#xff09;2.3.Cpolar稳定隧道&#xff08;本地设置&#xff09; 3. 公网访问测试总结 前言 博客作为使…

使用Docker部署Docker-Compose-Ui工具并实现公网访问

文章目录 1. 安装Docker2. 检查本地docker环境3. 安装cpolar内网穿透4. 使用固定二级子域名地址远程访问 Docker Compose UI是Docker Compose的web界面。这个项目的目标是在Docker Compose之上提供一个最小的HTTP API&#xff0c;同时保持与Docker Compose CLI的完全互操作性。…

十大顶级电脑分区恢复软件,不用重装系统直接分区磁盘

与分区相关的问题总是令人不愉快&#xff0c;但解决它们并不像看起来那么困难。您只需要使用可用的最佳分区恢复软件&#xff0c;例如本文列出的 10 种解决方案。配备功能强大的分区数据恢复软件&#xff0c;无论分区损坏有多严重&#xff0c;您都应该能够立即恢复数据。 我们如…

【git 使用】使用 git rebase -i 修改任意的提交信息/合并多个提交

修改最近一次的提交信息的方法有很多&#xff0c;可以参考这篇文章&#xff0c;但是对于之前的提交信息进行修改只能使用 rebase。 修改提交信息 假设我们想修改下面这个提交信息&#xff0c;想把【登录】改成【退出登录】步骤如下 运行 git rebase -i head~3 打开了一个文本…

数据结构与算法:栈

朋友们大家好啊&#xff0c;在链表的讲解过后&#xff0c;我们本节内容来介绍一个特殊的线性表&#xff1a;栈&#xff0c;在讲解后也会以例题来加深对本节内容的理解 栈 栈的介绍栈进出栈的变化形式 栈的顺序存储结构的有关操作栈的结构定义与初始化压栈操作出栈操作获取栈顶元…