0-前置知识

前言

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

ApplicationContextInitializer

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

使用

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

示例

自定义类

public class MyApplicationContextInitializer implements ApplicationContextInitializer {// ioc容器对象创建完毕后执行@Overridepublic 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 {@Overridepublic void onApplicationEvent(ApplicationEvent event) {// ApplicationEvent event 对应的就是发布的事件,ApplicationReadyEvent,ApplicationFailedEventif (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 {@Beanpublic 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@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {// 注册一个Teacher的BeanDefinitionGenericBeanDefinition 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 {@Overridepublic void setBeanClassLoader(ClassLoader classLoader) {System.out.println("lxx...setBeanClassLoader..." + classLoader);}@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {System.out.println("lxx...setBeanFactory..." + beanFactory);}@Overridepublic 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 {// 销毁方法@Overridepublic void destroy() throws Exception {System.out.println("Animal...destroy");}// 初始化方法@Overridepublic 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对象初始化之前调用@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("MyBeanPostProcessor...postProcessBeforeInitialization..."+beanName);return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);}// Bean对象初始化之后调用@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("MyBeanPostProcessor...postProcessAfterInitialization..."+beanName);return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);}
}

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

git上传报错:Object too large, rejecting the pack

在gerrit设置了最大不能上传超过600M的文件&#xff0c;今天开发遇到推送问题&#xff1a; 结果到本地怎么也找不到大文件。 后来只能按commit排查&#xff0c;用如下命令排查到了&#xff1a; 解决方法,将大文件去掉&#xff1a;&#xff08;commitid为大文件所在commit&…

《初阶数据结构》尾声

目录 前言&#xff1a; 《快速排序&#xff08;非递归&#xff09;》: 《归并排序》&#xff1a; 《归并排序&#xff08;非递归&#xff09;》&#xff1a; 《计数排序》&#xff1a; 对于快速排序的优化&#xff1a; 分析&#xff1a; 总结&#xff1a; 前言&#xff1a…

linux学习笔记3——文件移动、复制、与搜索命令

对于文件夹操作&#xff0c;linux还支持移动——mv与复制——cp两个命令 mv文件名所要移动目录&#xff0c;具体可以使用.来代表当前目录 cp文件名所要复制目录&#xff0c;二者在目录栏均可对文件重命名 对于find命令&#xff0c;有很多种用法&#xff0c;这里find加所搜索文…

Azkaban【基础 01】核心概念+特点+Web界面+架构+Job类型(一篇即可入门Azkaban工作流调度系统)

Azkaban工作流调度系统 1. 工作流调度系统解决了什么问题2. 特点3. 与Ooize简单对比4. 架构5. Job类型6. 总结 1. 工作流调度系统解决了什么问题 我曾经参与过一个数据治理的项目&#xff0c;项目的大概流程是【数据获取-数据清洗入库-展示】&#xff1a; 这时候就出现问题了&…

【讨论】Web端测试和App端测试的不同,如何说得更有新意?

Web 端测试和 App 端测试是针对不同平台的上的应用进行测试&#xff0c;Web应用和App端的应用实现方式不同&#xff0c;测试时的侧重点也不一样。 Web端应用和App端应用的区别&#xff1a; 平台兼容性 安装方式 功能和性能 用户体验 更新和维护 测试侧重点有何不同 平台…

进程间如何进行通信?

进程间如何进行通信&#xff1f; 本文转自 公众号 ByteByteGo&#xff0c;如有侵权&#xff0c;请联系&#xff0c;立即删除 在 Linux 上&#xff0c;进程之间如何通信&#xff1f; 下图显示了进程间通信的 5 种方式。 01 管道&#xff08;Pipe&#xff09; 管道是单向字节流…

Java入门-可重入锁

可重入锁 什么是可重入锁? 当线程获取某个锁后&#xff0c;还可以继续获取它&#xff0c;可以递归调用&#xff0c;而不会发生死锁&#xff1b; 可重入锁案例 程序可重入加锁 A.class,没有发生死锁。 sychronized锁 package com.wnhz.lock.reentrant;public class Sychroniz…

泽攸科普——扫描电子显微镜(SEM)像衬度形成原理

扫描电镜通过电子束在样品表面进行周而复始的扫描运动&#xff0c;同时实时监测各种信号图像的产生&#xff0c;然后根据产生的信号多少来调制图像。 引起各种信号产生的扫描电镜图像衬度的来源有三个方面&#xff1a; 1. 试样本身性质&#xff1a;包括表面的凹凸不平、成分的…

哪些软件可以把试卷照片转换成电子版?试试这些软件

哪些软件可以把试卷照片转换成电子版&#xff1f;在数字化时代&#xff0c;纸质试卷的保存和传输都显得不太方便。为了解决这个问题&#xff0c;我们可以将试卷照片转换成电子版。下面&#xff0c;我将为大家介绍5款可以轻松实现这一功能的软件&#xff0c;让你轻松应对各种试卷…

代码随想录算法训练营第58天 | 392.判断子序列 115.不同的子序列

判断子序列 这道题可以双指针方法解决。 class Solution { public:bool isSubsequence(string s, string t) {int s_index 0;for(int t_index 0; t_index < t.size(); t_index) {if(s[s_index] t[t_index]) {s_index;}}return s_index s.size();} };用动态规划也是可解…

对象池模式-Object Pool Pattern

原文地址:https://jaune162.blog/design-pattern/object-pool-pattern/ 原文中可下载高清SVG矢量类图 引言 对象池模式(Object Pool Pattern)是一种创建一组可重用对象的设计模式。它通过维护一个预分配的对象集合,避免了频繁地创建和销毁对象所带来的性能开销。在需要使用…

MasterAlign背光贴合视觉应用软件说明书

今天为大家介绍下MasterAlign视觉软件在背光贴合行业中该如何使用