[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时计算机的…

量化交易全流程(五)

本节目录 策略回测 多因子模型 本节主要讨论回测相关的内容&#xff0c;包括两种不同的回测机制&#xff0c;即向量化回测和事件驱动回测&#xff1b;如何灵活使用开源工具来编写自己的回测程序&#xff1b;不同实现方式的优劣对比等。 在我们研究策略的时候&#xff0c;需要…

司空见惯 - 奈尔宝的NTTP

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

Qt模块、Qt开发应用程序类型、Qt未来主要市场、Qt6功能普及

Qt模块、Qt开发应用程序类型、Qt未来主要市场、Qt6功能普及 文章目录 1.Qt核心模块2.Qt的功能拓展3.Qt未来主要市场4.Qt6功能普及5.弃用的功能&#xff1a; Qt是一个跨平台的应用程序开发框架&#xff0c;提供了丰富的模块和工具来开发各种类型的应用程序。以下是Qt目前已有的…

【匠心打造】从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 测…

ffmpeg Operation not permitted

在ffmpeg合并视频的时候报这个错&#xff0c;一开始以为权限问题&#xff0c;后来发现是文件不安全&#xff0c;加 -safe 0 修改后代码&#xff1a; def mer_mp4(*args, save_path):tmp Path(args[0]) / Path(args[0]).parent / Path(video.txt)f open(tmp, w)for mp4 in a…

在线OJ项目核心思路

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

docker portainer部署

拉取镜像 docker pull portainer/portainer安装镜像 # 启动镜像, -v /var/run/docker.sock:/var/run/docker.sock&#xff1a;将主机上的 /var/run/docker.sock 文件挂载到容器的相同位置&#xff0c;使得 Portainer 可以通过 Docker API 访问主机上的 Docker 引擎。 docker …

决策树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…

C#实现十大经典排序算法:冒泡排序、选择排序、插入排序、希尔排序、归并排序、堆排序、计数排序、桶排序、基数排序

以下是使用C#实现十大经典排序算法的示例代码: 1. 冒泡排序(Bubble Sort) void BubbleSort(int[] array) {int n = array.Length;for (int i = 0; i < n - 1; i++){for (int j = 0; j < n - i - 1; j++){if (array[j] > array[j + 1]){int temp = array[j];array…

软考 系统架构设计师系列知识点之软件架构风格(4)

接前一篇文章&#xff1a;软考 系统架构设计师系列知识点之软件架构风格&#xff08;3&#xff09; 这个十一注定是一个不能放松、保持“紧”的十一。由于报名了全国计算机技术与软件专业技术资格&#xff08;水平&#xff09;考试&#xff0c;11月4号就要考试&#xff0c;因此…

vscode 注释插件koroFileHeader

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

2020ICPC银川(A E G J K)

2020ICPC银川(A E G J K) 2020ICPC银川 A. Best Player&#xff08;模拟&#xff09; 在某一维方向上无法区分的点显然另两维坐标相同 &#xff0c; 那么在当前维度上能区分的点个数就是本质不同的另两维坐标组成的点对的个数 &#xff0c; 用set维护一下即可。 #include&l…

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…