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

news2024/11/20 12:37:05

[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{
    @Override
    public 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 {
    
        @Bean
        public DBConnection lambdaConn() {
            return new Lambda();
        }
    }
    
    

    bean id 默认为方法名

  3. 将 bean 注入到 controller

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

    @RestController
    public class FirstRestController {
        private DBConnection dbconn;
    
        @Autowired
        public 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
          @Lazy
          public class MySQL implements DBConnection {
          }
      
      

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

      在这里插入图片描述


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

          @Configuration
          public class DBConfig {
      
              @Bean
              @Lazy
              public DBConnection lambdaConn() {
                  return new Lambda();
              }
      
              @Bean
              @Lazy
              public  DBConnection mongoDBConn() {
                  return new MongoDB();
              }
          }
      
      
      

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

      改完后效果如下:

      在这里插入图片描述


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

      @RestController
      public class FirstRestController {
          private DBConnection dbconn;
      
          @Autowired
          @Lazy
          public 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 {
        @PostConstruct
        public void init() {
            // init logic
        }
    }
    
  • 通过实现 InitializingBean 进行重载

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

cleanup

也是三种实现方式

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

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

    public class MySQL implements DBConnection, DisposableBean {
        @Override
        public 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;

    @Autowired
    public 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.coloradmin.cn/o/1059086.html

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

相关文章

Doctest:让你的测试更简单高效

简介&#xff1a;Doctest 是 Python 标准库的一部分&#xff0c;它允许开发者通过在文档字符串&#xff08;docstrings&#xff09;中编写示例来进行测试。这不仅可以在确保代码正确性的同时编写文档&#xff0c;还可以让读者更容易理解代码的用法和期望的输出。 历史攻略&…

(枚举 + 树上倍增)Codeforces Round 900 (Div. 3) G

Problem - G - Codeforces 题意&#xff1a; 思路&#xff1a; 首先&#xff0c;目标值和结点权值是直接联系的&#xff0c;最值不可能直接贪心&#xff0c;一定是考虑去枚举一些东西&#xff0c;依靠这种枚举可以遍历所有的有效情况&#xff0c;思考的方向一定是枚举 如果去…

云安全之等级保护介绍

网络安全部门概述 网络安全部门 1. 公安部 网安/网警/网监:全称“公共信息网络安全监察”&#xff0c;后改为“网络安全保卫部门”。 简称网监&#xff0c;是中华人民共和国公安部门的一项职责&#xff0c;具体实施这一职责的机构称为网监机关或网监部门(公共信息网络安全监…

kubernetes集群kubeadm方式安装

测试网络和DNS解析 kubectl run busybox --image busybox:1.28 --restart=Never --rm -it busybox -- sh ping www.baidu,com nslookup kubernetes.default.svc.cluster.localbusybox要用指定的1.28版本,不能用最新版本,最新版本,nslookup会解析不到dns和ip 延长kubernetes…

2023腾讯云轻量应用服务器和普通服务器有什么区别?

腾讯云轻量服务器和云服务器有什么区别&#xff1f;为什么轻量应用服务器价格便宜&#xff1f;是因为轻量服务器CPU内存性能比云服务器CVM性能差吗&#xff1f;轻量应用服务器适合中小企业或个人开发者搭建企业官网、博客论坛、微信小程序或开发测试环境&#xff0c;云服务器CV…

力扣 -- 279. 完全平方数(完全背包问题)

解题步骤&#xff1a; 参考代码&#xff1a; 未优化代码&#xff1a; class Solution { public:int numSquares(int n) {const int INF0x3f3f3f3f;int msqrt(n);//多开一行&#xff0c;多开一列vector<vector<int>> dp(m1,vector<int>(n1));//初始化第一行…

苹果ios系统ipa文件企业签名是什么?优势是什么?什么场合需要应用到?

企业签名是苹果开发者计划中的一种签名类型&#xff0c;允许企业开发者签署和分发企业内部使用的应用程序&#xff0c;而无需通过App Store进行公开发布。通过企业签名&#xff0c;企业可以在内部部署自己的应用程序&#xff0c;以满足特定的业务需求。 企业签名能够做到以下…

【Java 进阶篇】JDBC工具类详解

JDBC&#xff08;Java Database Connectivity&#xff09;是Java程序与数据库之间交互的标准接口&#xff0c;它允许Java应用程序连接到不同类型的数据库并执行数据库操作。在实际开发中&#xff0c;为了提高代码的可维护性和可重用性&#xff0c;通常会创建JDBC工具类来封装与…

【算法导论】线性时间排序(计数排序、基数排序、桶排序)

引言&#xff1a;   在排序的最终结果中&#xff0c;个元素的次序依赖于它们之间的比较&#xff0c;我们把这类排序算法称为比较排序&#xff0c;对于包含n个元素的输入序列来说&#xff0c;任何比较排序在最坏情况下都要经过 Ω ( n l g n ) \Omega(nlgn) Ω(nlgn)次比较&a…

【RuoYi项目分析】在RuoYi网关实现验证码功能

文章目录 1. 验证码功能的类清单2. 验证码的实现2.1. 验证码的获取2.2. 验证码的校验 3. 总结4. 资料参考 本文主要介绍了用户如何实现验证码&#xff0c;以及该功能如何与 Spring Gateway 联系起来。 1. 验证码功能的类清单 类功能CaptchaProperties验证码的 yml 配置Captcha…

算法-数学-斜率-直线上最多的点数

算法-数学-斜率-直线上最多的点数 1 题目概述 1.1 题目出处 https://leetcode.cn/problems/max-points-on-a-line/ 1.2 题目描述 给你一个数组 points &#xff0c;其中 points[i] [xi, yi] 表示 X-Y 平面上的一个点。求最多有多少个点在同一条直线上。 2 暴力搜索斜率…

Go 基本数据类型和 string 类型介绍

Go 基础之基本数据类型 文章目录 Go 基础之基本数据类型一、整型1.1 平台无关整型1.1.1 基本概念1.1.2 分类有符号整型&#xff08;int8~int64&#xff09;无符号整型&#xff08;uint8~uint64&#xff09; 1.2 平台相关整型1.2.1 基本概念1.2.2 注意点1.2.3 获取三个类型在目标…

postgresql-自增字段

postgresql-自增字段 标识列IdentitySerial类型Sequence序列 标识列Identity -- 测试表 create table t_user( -- 标识列自增字段user_id integer generated always as identity primary key,user_name varchar(50) not null unique );-- 自动生成序列 CREATE SEQUENCE public…

学位论文的写作方法,较好的参考文章

摘要 结合2个文章&#xff1a; [1]程鑫. 网联环境下交通状态预测与诱导技术研究[D]. 长安大学, 2017. [2]吴昊. 关中平原水资源变化特征与干旱脆弱性研究[D]. 长安大学, 2018. 主要研究内容及技术路线 各章小结和引言的写作 [1]程鑫. 网联环境下交通状态预测与诱导技术…

一文拿捏分布式协调Redis客服端-Redisson

Redisson 1.介绍 Redisson - 是一个高级的分布式协调Redis客服端 , 专注于分布式系统开发&#xff0c;让用户可以在分布式系统中很方便的去使用Redis。 2.相关使用 1.加锁 //底层是lua脚本保证了加锁的原子性 // 一直等待获取锁&#xff0c;直到获取到锁为止! 默认锁的存活…

【SimpleDateFormat】线程不安全问题分析及解决方案

前言 在日常开发中&#xff0c;我们经常需要去做日期格式转换&#xff0c;可能就会用到SimpleDateFormat类。但是&#xff0c;如果使用不当&#xff0c;就很容易引发生产事故&#xff01; 1. 问题推演 1.1 初始日期工具类 刚开始的日期转换工具类可能长这样&#xff1a; p…

nodejs+vue晓海网上订餐系统elementui

管理员功能需求 管理员登陆后&#xff0c;主要模块包括首页、个人中心、用户管理、菜单信息管理等功能。 第三章 系统分析 10 3.1需求分析 10 3.2可行性分析 10 3.2.1技术可行性&#xff1a;技术背景 10 3.2.2经济可行性 11 3.2.3操作可行性&#xff1a; 11 3.3性能分析 11 3.4…

创建GCP service账号并管理权限

列出当前GCP项目的所有service account 我们可以用gcloud 命令 gcloud iam service-accounts list gcloud iam service-accounts list DISPLAY NAME EMAIL DISABLED terraform …

数据结构 1.1 初学数据结构

数据结构的基本概念 数据结构在学什么&#xff1f; 如何用程序代码把现实世界的问题信息化 如何用计算机高效处理信息从而创造价值 数据&#xff1a; 数据元素、数据项&#xff1a; 数据元素——描述一个个体 数据对象——数据元素之间具有同样的性质 同一个数据对象里的数…

BGP高级特性——4字节AS号

目录 4字节AS号 相关概念 两种过渡属性 4字节AS号的格式 4字节AS号建立邻居 4字节AS号路由传递 配置命令 4字节AS号 相比于2字节AS号&#xff0c;范围更大。由1~65535扩展到1~4294967295 支持4字节AS号的BGP设备兼容仅支持2字节AS号的BGP设备 相关概念 Speaker&#…