spring原理(自学第六天)

news2024/9/21 2:30:50

Aware 接口及 InitializingBean 接口

今天将会学到Aware 接口及 InitializingBean 接口

我们可以先了解他们的作用:

 1. Aware 接口用于注入一些与容器相关信息, 例如
                a. BeanNameAware 注入 bean 的名字
                b. BeanFactoryAware 注入 BeanFactory 容器
                c. ApplicationContextAware 注入 ApplicationContext 容器
                d. EmbeddedValueResolverAware ${}
2. InitializingBean 接口提供了一种【内置】的初始化手段

明白了作用我们可以写两个配置类来验证

配置类一我们用正常注解的方式注入bean以及实现bean的初始化方法

@Configuration
public class MyConfig1 {

    private static final Logger log = LoggerFactory.getLogger(MyConfig1.class);

    @Autowired
    public void setApplicationContext(ApplicationContext applicationContext) {
        log.debug("@Autowired注入 ApplicationContext");
    }

    @PostConstruct
    public void init() {
        log.debug("@PostConstruct初始化");
    }

    @Bean //  beanFactory 后处理器
    public BeanFactoryPostProcessor processor1() {
        return beanFactory -> {
            log.debug("执行 processor1");
        };
    }

}

配置类二我们用实现上述两个接口的方法来实现注入bean以及实现bean的初始化方法 

@Configuration
public class MyConfig2 implements InitializingBean, ApplicationContextAware {

    private static final Logger log = LoggerFactory.getLogger(MyConfig2.class);

    @Override
    public void afterPropertiesSet() throws Exception {
        log.debug("初始化");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        log.debug("注入 ApplicationContext");
    }

    @Bean //  beanFactory 后处理器
    public BeanFactoryPostProcessor processor2() {
        return beanFactory -> {
            log.debug("执行 processor2");
        };
    }
}

创建启动类,并将这两个配置类bean对象注入容器中,观察结果

public class Spring06Application {

    public static void main(String[] args) {
         //创建一个干净的容器
        GenericApplicationContext context = new GenericApplicationContext();
        //注入bean
        context.registerBean("myConfig1", MyConfig1.class);
        context.registerBean("myConfig2", MyConfig2.class);
        
        //初始化容器
        context.refresh();
        for (String name : context.getBeanDefinitionNames()) {
               System.out.println(name);
        }
        
        //销毁容器
        context.close();
        
    }
}

可以看到两个配置类的bean对象都成功注入容器当中,但是只有实现接口的方法实现了bean对象的注入以及bean的初始化方法(由于容器中缺少了解析bean的bean后处理器) 

 我们往容器中添加bean后处理器解析注解

        context.registerBean(AutowiredAnnotationBeanPostProcessor.class);
        context.registerBean(CommonAnnotationBeanPostProcessor.class);

此时可以看到利用注解的方式注入bean也成功实现,bean的初始化方法也成功实现 

总结:实现Aware 接口及 InitializingBean 接口,由于提供了内置的注入方法,所以不需要依赖与bean的后处理器,注解方式需要依赖与bean后处理器,用 @Autowired 就能实现啊, 为啥还要用 Aware 接口呢
            简单地说:
                a. @Autowired 的解析需要用到 bean 后处理器, 属于扩展功能
                b. 而 Aware 接口属于内置功能, 不加任何扩展, Spring 就能识别
            某些情况下, 扩展功能会失效, 而内置功能不会失效

我们再容器中添加添加解析bean注解的后处理器,把beanfactory后处理器注入容器中观察结果

public class Spring06Application {

    public static void main(String[] args) {
         //创建一个干净的容器
        GenericApplicationContext context = new GenericApplicationContext();
        //注入bean
//        context.registerBean("myBean",MyBean.class);
        context.registerBean("myConfig1", MyConfig1.class);
        context.registerBean("myConfig2", MyConfig2.class);

        context.registerBean(AutowiredAnnotationBeanPostProcessor.class);
        context.registerBean(CommonAnnotationBeanPostProcessor.class);
        context.registerBean(ConfigurationClassPostProcessor.class);
        //初始化容器
        context.refresh();

        for (String name : context.getBeanDefinitionNames()) {
            System.out.println(name);
        }
        //销毁容器
        context.close();

    }
}

可以看到用注解注入的bean以及初始化方法并没有被成功解析

对比

  • 内置的注入和初始化不受扩展功能的影响,总会被执行

  • 而扩展功能受某些情况影响可能会失效

  • 因此 Spring 框架内部的类常用内置注入和初始化

配置类 @Autowired 失效分析

Java 配置类包含 BeanFactoryPostProcessor 的情况,因此要创建其中的 BeanFactoryPostProcessor 必须提前创建 Java 配置类,而此时的 BeanPostProcessor 还未准备好,导致 @Autowired 等注解失效  

注意

解决方法:

  • 用内置依赖注入和初始化取代扩展依赖注入和初始化

  • 用静态工厂方法代替实例工厂方法,避免工厂对象提前被创建

初始化与销毁(初始化销毁顺序 )

 准备好类并实现初始化方法接口(此时有注解方式实现初始化,接口方式实现初始化,bean注解方式指定初始化方法)

public class Bean1 implements InitializingBean {
    private static final Logger log = LoggerFactory.getLogger(Bean1.class);

    @PostConstruct
    public void init1() {
        log.debug("初始化1");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        log.debug("初始化2");
    }

    public void init3() {
        log.debug("初始化3");
    }
}

创建类实现销毁方法接口

public class Bean2 implements DisposableBean {
    private static final Logger log = LoggerFactory.getLogger(Bean2.class);

    @PreDestroy
    public void destroy1() {
        log.debug("销毁1");
    }

    @Override
    public void destroy() throws Exception {
        log.debug("销毁2");
    }

    public void destroy3() {
        log.debug("销毁3");
    }
}

Spring 提供了多种初始化手段,除了课堂上讲的 @PostConstruct,@Bean(initMethod) 之外,还可以实现 InitializingBean 接口来进行初始化,如果同一个 bean 用了以上手段声明了 3 个初始化方法,那么它们的执行顺序是

  1. @PostConstruct 标注的初始化方法

  2. InitializingBean 接口的初始化方法

  3. @Bean(initMethod) 指定的初始化方法

与初始化类似,Spring 也提供了多种销毁手段,执行顺序为

  1. @PreDestroy 标注的销毁方法

  2. DisposableBean 接口的销毁方法

  3. @Bean(destroyMethod) 指定的销毁方法

扩展:

1.aware接口执行在@PostConstruct 标注的初始化方法InitializingBean 接口的初始化方法之间,

2.执行destroySingletons()方法销毁之后,仍可创建新的单例

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

解锁LLM应用潜能:提示工程的39种方法与应用全解析!

大型语言模型(LLMs)在许多不同的自然语言处理(NLP)任务上表现出了显著的性能。提示工程在提升LLMs已有能力方面发挥着关键作用,使其在各种NLP任务上取得了显著的性能提升。提示工程需要编写自然语言指令,即…

QT 应用程序输出中文乱码

一 ,选择文本编码 1. 点击编辑再点击Select Encoding选择编码 2 .在弹出的窗口,选择UTF-8再点击按编码保存即可 3. 重新编译,可以发现中文乱码问题解决

Spring源码解析(28)之AOP的核心对象创建过程总结

一、总结图 二、总结 以上是对AOP核心对象创建的一个总结,接下来我们分点介绍我们自从定义了aop.xml之后,spring在启动的时候是怎么创建了这些核心对象的。 启动spring容器之后,其实核心是是refresh方法,refresh的13个核心方法&…

CTFHub——XSS——反射型

1、反射型: 发现为表单式,猜测哪个可能存在注入漏洞,分别做测试注入发现name框存在xss漏洞 输入发现有回显但不是对方cookie,参考wp发现要用xss线上平台 将xss平台测试语句注入,将得到的url编码地址填入url框&#xf…

Lineage凌骥电源模块维修CP2725AC54Z

Lineage Power交换机电源常见维修型号有: CAR2024FPZ0-1A、CP2725AC54TEZ、AXA005A0X-SRZ、APXW005A0X3-SRZ、AXA016A0X3-SRZ、EP3000AC48TE、CP3000AC54TEZ、 CP3000AC54TEZ、QBDW033A0B641Z及EP4848系列直流电源维修等。 凌骥电源维修实践中,有许多开关…

【OpenCV C++20 学习笔记】击中击不中(Hit-or-Miss)

击中击不中 Hit-or-Miss 原理代码实现 原理 形态学操作对图片的处理是基于图片的形状的。形态学操作将一个或多个结构元素(structuring elements),即卷积核,应用到图片上从而获得计算结果。最基本的两个形态学操作就是腐蚀(erosion)和膨胀(dilation)。这…

7 时间序列单特征:多输入->多输出(LSTM/GRU/TCN)

今天看到关于时间序列预测知识点,竟然要收费!本着开源第一的思想,自己也找到相关的代码尝试一下写几个通用的模版。 模型想要 输入:Input (input_size, hidden_size),其中:input_size time_stemp,因为是单个变量因此…

从实现第一个ArkTs应用开始入门

前言 新建了个鸿蒙学习项目,后续持续学习会把代码放到这里来:鸿蒙项目仓库学习实践版 基本概念 从HarmonyOS NEXT Developer Preview1(API 11)版本开始,HarmonyOS SDK以Kit维度提供了六大领域的开放能力, 包括: 应用…

800G FR4解决方案:高速数据传输的理想选择

随着业务规模的扩大,数据中心面临着越来越多的数据处理需求。虚拟化、物联网(IoT)和云计算等数据密集型应用推动了数据中心流量的不断增长,从而提升了对大容量800G解决方案的市场需求。因此,新建800G数据中心&#xff…

marker - PDF 转 markdown

文章目录 一、关于 marker特点它是如何工作的例子性能商业用途托管API限制 二、安装Optional: OCRMyPDF 三、用法1、配置转换单个文件转换多个文件在多个GPU上转换多个文件 三、故障排除四、有用的设置五、基准测试速度精度吞吐量 六、运行自己的基准测试七、感谢 一、关于 mar…

C++初学(9)

9.1、结构简介 虽然数组能够和存储多个元素,但所有元素必须相同,也就是说,同一个数组不能既存放int类型也存放float类型,而C的结构可以满足要求。结构是一种比数组更灵活的数据格式,因为同一个结构可以存储多种类型的…

防御笔记第九天(持续更新)

注意:攻击可能只是一个点,而防御需要全方面进行。 1.IAE引擎 2.DPI DPI ----深度包检测 --- 针对完整的数据包,进行内容的识别和检测 3.基于特征字的检测技术 4,基于应用网关的检测技术 基于应用网关的检测技术 --- 有些应用控…

数据库方言

数据库方言,也称数据库领域特定语言(DSL),是针对特定数据库系统的专有扩展或子集,它允许用户在特定环境内使用更高效、更简洁的查询语句。 关键字(Keywords) 关键字是数据库方言中预定义的单词&…

Windows 安装Redis7.4版本图文教程

本章教程,主要介绍如何在Windows上安装Redis7.4版本的Redis,并以服务方式实现开机自启动。 1、下载安装包 通过百度网盘分享的文件:Redis-7.4.0-Windows-x64-cygwin-with-Service.zip 链接:https://pan.baidu.com/s/1NFGXrCwumDzl…

【计算机毕业设计】703学生考勤管理系统

🙊作者简介:拥有多年开发工作经验,分享技术代码帮助学生学习,独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。🌹赠送计算机毕业设计600个选题excel文件,帮助大学选题。赠送开题报告模板&#xff…

软件测试 -- 黑盒、灰盒、白盒测试,冒烟测试、回归测试

软件测试目的:查找软件中缺陷(bug),保障软件质量。

IPV6公网暴露下的OPENWRT防火墙安全设置(只允许访问局域网中指定服务器指定端口其余拒绝)

首先是防火墙的常规配置和区域配置 标的有点乱但是选项含义都做了解释,看不懂可以直接按图抄作业。 其次是对需要访问的端口做访问放通 情况1 DDNS位于openwrt网关上,外网访问openwrt,通过端口转发访问内部服务器。此情况需要设置端口转发。 …

6-4 填充和步幅

在前面的例子 图6.2.1中,输入的高度和宽度都为 3 3 3,卷积核的高度和宽度都为 2 2 2,生成的输出表征的维数为 2 2 2\times 2 22。 正如我们在 6-2节中所概括的那样,假设输入形状为 n h n w n_{h}\times n_{w} nh​nw​&#xff…

大象机器人水星MercuryX1轮式人形机器人基于物体标记建模的键盘点按操作!

引言 在现代科技的推动下,机器人在日常生活和工作场景中的应用越来越广泛。本文将介绍MercuryX1,这款先进的机器人如何通过其手臂末端的摄像头识别并确定键盘的键位,从而进行精确的打字操作。通过这一案例,我们将展示MercuryX1在自…

xcode使用

1. 界面 1.1. Build Settings,Build Phases和Build Rules三个设置项 Build Settings(编译设置): 每个选项由标题(Title)和定义(Definition)组成。这里主要定义了Xcode在编译项目时的一些具体配置 Build Phases(编译资源):用于指定编译过程中项目所链接的原文件,依赖对象,库…