[spring] spring core - 配置注入及其他内容补充

[spring] spring core - 配置注入及其他内容补充

上篇 [sping] spring core - 依赖注入

这里主要补一些 core 相关内容补充,同时添加了 java config bean 的方法

java config bean 是除了 XML、java 注解之外另一给实现 DI 的方法

java config bean

这个方法不使用 annotation,而是使用 @Configure 类实现

首先实现一个不使用注解的类:

package com.example.demo;public class Lambda implements DBConnection{@Overridepublic String connect() {return  "Connection via Lambda";}
}

将这个类注入到 controller 的过程为:

  1. 创建 @Configure

    package com.example.demo;import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;@Configuration
    public class DBConfig {
    }
  2. 定义 @Bean 方法去配置 bean

    
    @Configuration
    public class DBConfig {@Beanpublic DBConnection lambdaConn() {return new Lambda();}
    }

    bean id 默认为方法名

  3. 将 bean 注入到 controller

    这里依旧使用 @Qualifier("lambdaConn") 去实现:

    @RestController
    public class FirstRestController {private DBConnection dbconn;@Autowiredpublic void setDBconn(@Qualifier("lambdaConn") DBConnection dbconn) {System.out.println("dbconn from setter");this.dbconn = dbconn;}}
    

    效果如下:

    在这里插入图片描述

java config bean vs annotation

二者的优缺点还是比较明显的

方法优点缺点
注解
  • 简单
  • boilerplate 代码少
  • 直观
  • 难以溯源,尤其是当代码量大起来的时候,寻找对应的依赖会比较困难
  • 耦合度较高
java-based-config
  • 集中配置
  • 灵活性,尤其是对接第三方代码或是 legacy 代码
  • 低耦合
  • boilerplate 代码较多
  • 学习曲线更为陡峭

一般推荐方案有:

  • 中小型项目,代码量较少的情况下,使用注解
  • 中大型项目使用 java 配置
  • 在有需求的时候进行混用,特别是对于无法控制的第三方库,或是一时半会儿没法重构的代码
  • 考虑使用 spring profile @Profile 代替 java config

component scan

关于 component scan,spring 会扫面 entry point——即有 @SpringBootApplication 的 java class——的统计和子 package,如果结构更新成下面这样的:

在这里插入图片描述

util 中的 class 不会被 spring 自动扫到:

在这里插入图片描述

想要让 spring 扫到 util 下的代码,需要使用在 @SpringBootApplication 中添加 scanBasePackages,如:

@SpringBootApplication(scanBasePackages = {"com.example.util"})
public class DemoApplication {// ...
}

除了有 scanBasePackages 之外,还有 scanBasePackageClasses

懒初始化

在 spring 项目启动时,所有的 bean 默认都完成初始化。我在构造函数里面添加了一行 System.out.println("In constructor: " + getClass().getSimpleName()); 后,终端显示如下:

在这里插入图片描述

可以看到,在 LiveReload 和 Tomcat 启动之前,所有的 bean 都完成了实例化。

这也就意味着项目在启动初期一定会更加耗时,想要对其优化,可以使用懒初始化(lazy initialization)。这样 bean 只有在这两个情况下会被初始化:

  • 被其他的 bean 进行调用
  • 直接请求当前 bean

实现的方法有三种:

  • 全局化实现

    这个在 spring boot 中的配置文件,如 application.properties 中实现:

    spring.main.lazy-initialization=true
    
  • 使用 @Lazy 注解

    这个又可以分成多种情况:

    • 直接使用 @Component 的,可以在 @Component 中加:

          @Component@Lazypublic class MySQL implements DBConnection {}

      这时候 MySQL 就不会显示完成加载:

      在这里插入图片描述


    • Java Config 中可以在对应的 bean 上加,如:

          @Configurationpublic class DBConfig {@Bean@Lazypublic DBConnection lambdaConn() {return new Lambda();}@Bean@Lazypublic  DBConnection mongoDBConn() {return new MongoDB();}}

      我这里添加了一个 MongoDB,因为 lambdaConn 在启动 rest controller 时被请求,所以肯定是要实例化才能进行下一步的。

      改完后效果如下:

      在这里插入图片描述


    • 在被 @Autowired 地方的添加 @Lazy

      @RestController
      public class FirstRestController {private DBConnection dbconn;@Autowired@Lazypublic void setDBconn(@Qualifier("lambdaConn") DBConnection dbconn) {System.out.println("dbconn from setter");this.dbconn = dbconn;}}

      这个情况下,只有当该 rest controller 被访问时,才会进行初始化:

      在这里插入图片描述

      JDBC 是唯一一个没有被添加 @Lazy 的类,因此一开始它就被初始化了

      随后可以看到,尽管这里用的是 setter 注入,但是却没有对象被实例化,一直到服务器启动了,网页被访问之后,Lambda 对象才被实例化

  • XML 中也可以添加 lazy-init 属性实现,不过我这没 XML 的案例,就不贴代码了

总体来说,懒初始化可以提升项目启动速度,不过这个成本可能会加到运行的时候,因此在做优化时还是要跑一些 metrics 去最终决定是否要实现懒初始化,或是哪些 bean 被懒初始

bean 生命周期

上网找了一下,大体的流程是这样的:

在这里插入图片描述

不过教程没有细说,之时提了两个比较常用的 lifecycle callback:init 和 cleanup。前者在 bean 准备被使用前调用,这里可以处理一些 side effect,如链接 db,新建 socket 等,后者则是在 bean 被销毁前调用,用来清理一些 side effect

init

有三种方式可以实现:

  • XML

    <bean id="someBeanId" class="some.class" init-method="method-name" />
    
  • 注解

    public class MySQL implements DBConnection {@PostConstructpublic void init() {// init logic}
    }
    
  • 通过实现 InitializingBean 进行重载

    public class MySQL implements DBConnection, InitializingBean {@Overridepublic void afterPropertiesSet() throws Exception {}
    }
    

cleanup

也是三种实现方式

  • XML
<bean id="someBeanId" class="some.class" destroy-method="method-name" />
  • 注解

    public class MySQL implements DBConnection {@PreDestroypublic void cleanup() {// clean up logic}
    }
    
  • 实现 interface

    public class MySQL implements DBConnection, DisposableBean {@Overridepublic void destroy() throws Exception {}
    }
    

bean scope

bean scope 和它的生命周期,以及在 app 中的可见度(即被分享)有关,所有的 bean 默认都是 singleton。

目前官方提供的列表为:

scope描述
singleton默认,每个 IoC 容器只会生成一个
prototype每次容器新创建一个对象,就就会新创建一个 instance
request每个 HTTP 请求会生成一个新的 instance
只有在 web 项目中适用
session每个 HTTP session 中会生成一个 instance
只有在 web 项目中适用
application每个 ServletContext 生命周期会生成一个 instance
只有在 web 项目中适用
网页项目中与 singleton 相似
websocket同理,一个 websocket 生命周期中会生成一个 instance
只有在 web 项目中适用

XML 中的配置方法为:

<bean id="someBeanId" class="some.class" scope="a_valid_scope" />

使用 annotation 的方式为:

@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class Lambda implements DBConnection{// ...
}

这里简单的进行一下 shallow compare,即对比地址:

public class FirstRestController {private DBConnection dbconn;private DBConnection dbconn2;@Autowiredpublic void setDBconn(@Qualifier("lambdaConn") DBConnection dbconn, @Qualifier("lambdaCoÏnn") DBConnection dbconn2) {System.out.println("dbconn from setter");this.dbconn = dbconn;this.dbconn2 = dbconn2;}@GetMapping("/check")public String getCheck() {System.out.println(dbconn.getClass().getSimpleName());return "Comparing beans: dbconn" + (this.dbconn2 == this.dbconn ? "==" : "!=") + " dbconn2.";}
}

在 prototype 的情况下为 false:

在这里插入图片描述

在默认(singleton)的情况下为 true:

在这里插入图片描述

特殊的 prototype

prototype 的清理有一些特殊,因为 spring 不会对 prototype 的生命周期进行完整的干里,即不会调用对应的清理函数,所以如果某个 bean 需要经常被创建/毁灭,那么就要考虑是不是需要使用 prototype,还是应该使用其他的 scope

以及,prototype bean 默认就是懒初始化,所以没有必要添加 @Lazy

总结

在这里插入图片描述

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

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

相关文章

Tomcat报404问题的原因分析

1.未配置环境变量 按照需求重新配置即可。 2.IIs访问权限问题 注意:这个问题有的博主也写了,但是这个问题可有可无,意思是正常情况下,有没有都是可以访问滴放心 3.端口占用问题 端口占用可能会出现这个问题,因为tomcat的默认端口号是8080,如果在是运行tomcat时计算机的…

司空见惯 - 奈尔宝的NTTP

联合国对21世纪人才定义的标准&#xff0c;包括六种核心技能&#xff0c;即批判性思维&#xff08;critical thinking)、人际交往&#xff08;communication)、与人合作&#xff08;collaboration)、创造性&#xff08;creativity)、信息素养&#xff08;information literacy)…

【匠心打造】从0打造uniapp 可视化拖拽设计 c_o 第十篇

一、click one for uniapp置顶&#xff1a; 全部免费开源 (你商业用途也没关系&#xff0c;不过可以告诉我公司名或者项目名&#xff0c;放在官网上好看点。哈哈-_-) 二、写在之前 距离上一篇更新已经大约4个月了&#xff0c;公司的事情&#xff0c;自己的一些琐事一直没时间…

Excel·VBA分列、字符串拆分

看到一篇博客《VBA&#xff0c;用VBA进行分列&#xff08;拆分列&#xff09;的2种方法》&#xff0c;使用VBA对字符串进行拆分 目录 Excel分列功能将字符串拆分为二维数组&#xff0c;Split函数举例 将字符串拆分为一维数组&#xff0c;正则表达式举例 Excel分列功能 Sub 测…

在线OJ项目核心思路

文章目录 在线OJ项目核心思路1. 项目介绍2.预备知识理解多进程编程为啥采用多进程而不使用多线程?标准输入&标准输出&标准错误 3.项目实现题目API实现相关实体类定义新增/修改题目获取题目列表 编译运行编译运行流程 4.统一功能处理 在线OJ项目核心思路 1. 项目介绍 …

决策树C4.5算法的技术深度剖析、实战解读

目录 一、简介决策树&#xff08;Decision Tree&#xff09;例子&#xff1a; 信息熵&#xff08;Information Entropy&#xff09;与信息增益&#xff08;Information Gain&#xff09;例子&#xff1a; 信息增益比&#xff08;Gain Ratio&#xff09;例子&#xff1a; 二、算…

跟着顶级科研报告IPCC学绘图:温度折线/柱图/条带/双y轴

复现IPCC气候变化过程图 引言 升温条带Warming stripes&#xff08;有时称为气候条带&#xff0c;目前尚无合适且统一的中文释义&#xff09;是数据可视化图形&#xff0c;使用一系列按时间顺序排列的彩色条纹来视觉化描绘长期温度趋势。 在IPCC报告中经常使用这一方案 IPCC是…

【PostgreSQL】【存储管理】表和元组的组织方式

外存管理负责处理数据库与外存介质(PostgreSQL8.4.1版本中只支持磁盘的管理操作)的交互过程。在PostgreSQL中&#xff0c;外存管理由SMGR(主要代码在smgr.c中)提供了对外存的统一接口。SMGR负责统管各种介质管理器&#xff0c;会根据上层的请求选择一个具体的介质管理器进行操作…

凉鞋的 Godot 笔记 105. 第一个通识:编辑-测试 循环

105. 第一个通识&#xff1a;编辑-测试 循环 在这一篇&#xff0c;我们简单聊聊此教程中所涉及的一个非常重要的概念&#xff1a;循环。 我们在做任何事情都离不开某种循环&#xff0c;比如每天的 24 小时循环&#xff0c;一日三餐循环&#xff0c;清醒-睡觉循环。 在学习一…

首发Orin N芯片,腾势追赶「智驾第一梯队」

张祥威 编辑 | 德新 英伟达最新一代芯片—— Orin N&#xff0c;腾势拿下 首发。 9月26日&#xff0c;腾势N7推出「高快智驾包」。官方描述中&#xff0c;这一选装将“基于新一代NIVIDIA DRIVE ORIN的 高性能平台”&#xff0c;可以实现高速NOA。 此前&#xff0c;腾势的…

从零手搓一个【消息队列】实现虚拟主机的核心功能

文章目录 一、虚拟主机设计二、实现虚拟主机1, 创建 VirtualHost 类2, VirtualHost() 构造方法3, exchangeDeclare() 创建交换机4, exchageDelete() 删除交换机5, queueDeclare() 创建队列6, queueDelete() 删除队列7, queueBind() 创建绑定8, queueUnBind() 删除绑定9, basicP…

vscode 注释插件koroFileHeader

https://blog.51cto.com/u_15785499/5664323 https://blog.csdn.net/weixin_67697081/article/details/129004675

YoloV5实时推理最短的代码

YoloV5实时推理最简单代码 import cv2 import torch# 加载YOLOv5模型 model torch.hub.load(ultralytics/yolov5, yolov5s)# 使用CPU或GPU进行推理 device cuda if torch.cuda.is_available() else cpu model.to(device)# 打开摄像头&#xff08;默认摄像头&#xff09; cap…

vue pc端/手机移动端 — 下载导出当前表格页面pdf格式

一、需求&#xff1a;在手机端/pc端实现一个表格页面&#xff08;缴费单/体检报告单等&#xff09;的导出功能&#xff0c;便于用户在本地浏览打印。 二、实现&#xff1a;之前在pc端做过预览打印的功能&#xff0c;使用的是print.js之类的方法让当前页面直接唤起打印机的打印预…

【好玩的开源项目】Docker部署cook菜谱工具

【好玩的开源项目】Docker部署cook菜谱工具 一、cook菜谱工具介绍二、本地环境介绍2.1 本地环境规划2.2 本次实践介绍 三、本地环境检查3.1 检查Docker服务状态3.2 检查Docker版本 四、下载cook镜像五、部署cook菜谱工具5.1 创建cook容器5.2 查看容器状态5.3 检查容器日志 六、…

Oracle is和as 关键字学习

之前写的Oracle存储过程中都有is和as关键字&#xff1b;下面学习这二个关键字&#xff1b; Oracle中is可用于以下情况&#xff1a; 判断某个值是否为null。在Oracle中&#xff0c;null表示一个未知或不适用的值。因此&#xff0c;我们需要使用is null或is not null语句来检查某…

OpenNebula的配置与应用

学习了OpenNebula的安装之后&#xff0c;接下来就是配置OpenNebula&#xff0c;内容包括配置Sunstone&#xff0c;VDC和集群&#xff0c;设置影像&#xff0c;模板管理&#xff0c;虚拟机管理等。OpenNebula还有大量的工作要做&#xff0c;这些工作主要来自映像、模板和虚拟机管…

Redis主从复制、哨兵、cluster集群

目录 Redis 主从复制 主从复制的作用 主从复制流程 搭建Redis 主从复制 实验环境 所有主机安装redis 修改 Redis 配置文件&#xff08;Master节点操作&#xff09; 修改 Redis 配置文件&#xff08;Slave节点操作&#xff09; 验证主从效果 Redis 哨兵模式 哨兵模式的…

算法通过村第十一关-位运算|黄金笔记|位运算压缩

文章目录 前言用4kb内存寻找重复元素总结 前言 提示&#xff1a;如果谁对你说了地狱般的话&#xff0c;就代表了他的心在地狱。你不需要相信那样的话&#xff0c;就算对方是你的父母也一样。 --高延秀《远看是蔚蓝的春天》 位运算有个很重要的作用就是能用比较小的空间存储比较…

思科:iOS和iOSXe软件存在漏洞

思科警告说,有人试图利用iOS软件和iOSXe软件中的一个安全缺陷,这些缺陷可能会让一个经过认证的远程攻击者在受影响的系统上实现远程代码执行。 中严重程度的脆弱性被追踪为 CVE-2023-20109 ,并以6.6分得分。它会影响启用Gdoi或G-Ikev2协议的软件的所有版本。 国际知名白帽黑客…