【深入浅出Spring原理及实战】「夯实基础系列」360全方位渗透和探究Spring配置开发实战详解

news2024/11/27 4:36:24

360全方位渗透和探究Spring配置开发实战详解

  • Spring对于配置的转折点
  • Xml配置 vs Java配置
    • Xml配置模式的优点
    • Xml配置模式的缺点
    • Java配置模式的优点
    • Java配置模式的缺点
  • Java编程配置流程
    • 配置代码案例
  • 组件注入
    • Bean注解
      • 配置自动扫描包路径和规则
        • @Filter常用的拦截类型
        • FilterType.ASSIGNABLE_TYPE的过滤实现
        • FilterType.ANNOTATION的过滤实现
        • FilterType.ANNOTATION的过滤实现
        • FilterType.CUSTOM的过滤实现

Spring对于配置的转折点

我们都知道,Spring4在配置方式上有一个重要的变革点。在Spring4.x之前,通常使用XML配置来完成应用的基本配置,而在业务逻辑中则推荐使用注解方式。但是自从Spring4.x开始,官方推荐使用基于Java的编程配置来代替XML配置,这是一个重要的转变。

Xml配置 vs Java配置

Xml配置模式的优点

XML配置的优点在于对于老一辈程序员来说非常熟悉和简单,易于扩展,不需要重新编译就能修改应用配置参数。

Xml配置模式的缺点

XML配置的缺点是读取和解析配置文件需要耗费时间,当配置文件过多时会显得臃肿,管理起来不方便。

Java配置模式的优点

基于Java的编程配置的优点是结构更清晰,可读性更高,同时也节省了解析XML的时间。

Java配置模式的缺点

基于Java的编程配置的缺点是修改应用配置参数需要重新编译。然而,在实际的生产环境中,应用配置完成后很少会随意修改,因此这并不是一个大问题。

Java编程配置流程

在这里插入图片描述

  1. 配置类(通常命名为AppConfig),并在类名上添加@Configuration注解,这样告诉Spring这是一个配置类,类似于XML文件。

  2. 如果有外部配置文件,可以在类名上添加@PropertySource注解,并指定properties文件的路径。这样可以加载外部配置文件中的属性值。

  3. 在需要获取应用配置属性值的地方,可以在对应的变量上添加@Value注解,通过${}表达式来获取配置文件中的参数。

  4. 如果需要进行依赖注入,可以在相应的方法上添加@Bean注解,并返回对应的Bean对象。也可以使用FactoryBean来创建对应的Bean。

配置代码案例

在这个例子中,我们声明了一个配置类DataSourceConfiguration 。它使用@Configuration注解标识为配置类,@PropertySource注解引入了一个名为application.properties的外部文件,@ComponentScan配置了自动扫描的包路径。

/**
 * Spring 配置类
 * 配置数据源,事务管理,bean,自动扫描包
 */
@Configuration	// 声明该类为配置类
@PropertySource({"classpath:application.properties"})	// 引入外部文件
@ComponentScan("com.example")	// 配置自动扫描包的路径
public class DataSourceConfiguration {
    
 private String DB_USERNAME;
    
    @Value("${database.password}")
    private String DB_PASSWORD;
    
    @Value("${database.driver}")
    private String DB_DRIVER;
    
    @Value("${database.jdbcUrl}")
    private String DB_JDBC_URL;
    
    @Bean // 数据源
    public DataSource dataSource() {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setUser(DB_USERNAME);
        dataSource.setPassword(DB_PASSWORD);
        dataSource.setDriverClass(DB_DRIVER);
        dataSource.setJdbcUrl(DB_JDBC_URL);
        return dataSource;
    }
}

在配置类中,我们使用@Value注解来注入外部属性文件中的值。具体来说,我们注入了数据库用户名、密码、驱动和JDBC URL四个属性。

我们使用@Bean注解来定义了一个dataSource()方法,该方法返回一个数据源对象ComboPooledDataSource。在方法中,我们根据注入的属性值设置了数据源的相关属性,最终将数据源返回。

组件注入

在这里插入图片描述

  • Bean注解:Bean注解类似于XML文件中的标签,用于将一个方法或类标记为Spring容器中的一个组件。被Bean注解修饰的方法名对应标签中的id,也可以通过Bean注解的value属性设置id的值。在Spring Boot的底层代码中广泛使用。

  • 默认单实例:在Spring中,默认情况下,被注解为Bean的对象是单例的。即容器启动后会创建对象,并将其保存在容器中,以后每次使用时从容器中获取。

  • 懒加载:如果希望在需要使用时才创建对象,并将其保存在容器中以供下次使用,可以使用Lazy注解修饰对象。当使用到该对象时,容器会创建并保存,以后每次使用时都从容器中获取。

  • 多实例:如果希望每次使用时都创建一个新对象而不是使用先前创建的对象,则可以使用Scope注解。将其参数值设置为prototype,即@Scope(“prototype”)。

  • 条件注入:如果希望根据条件选择需要注入的Bean,可以使用注解Conditional进行条件判断。Spring Boot的底层代码中广泛使用该注解。

Bean注解

在这个例子中,我们使用@Bean注解来配置一个名为sampleBeanName的Bean。我们在方法名SampleBean ()上使用了@Bean注解,并将其value值设置为sampleBeanName,表示该Bean的id为sampleBeanName

@Bean(value="sampleBeanName")
public SampleBean sampleBean() {
    return new SampleBean ();
}

在方法内部,我们返回一个SampleBean 对象。这样,在容器启动时,会创建一个名为sampleBeanName的Bean,并将其保存在容器中,供其他组件使用。

通过这个例子,我们可以学习到如何使用@Bean注解来配置Bean,并设置Bean的id。这种方式相当于在XML文件中使用标签来配置Bean。

  1. 注解Bean的value值表示bean的id
  2. 注解Bean的value值未设置,则方法名表示bean的id

配置自动扫描包路径和规则

@Filter常用的拦截类型
  • FilterType.ANNOTATION:按照注解进行过滤
  • FilterType.ASSIGNABLE_TYPE:按照指定类型进行过滤,包括子类和实现类
  • FilterType.CUSTOM:使用自定义规则进行过滤
FilterType.ASSIGNABLE_TYPE的过滤实现

当使用FilterType.ASSIGNABLE_TYPE时,你可以根据给定的类型及其子类和实现类来进行过滤。下面是一个使用FilterType.ASSIGNABLE_TYPE的过滤实现的案例:

interface Animal {
    void makeSound();
}

class Dog implements Animal {
    public void makeSound() {
        System.out.println("Dog barks...");
    }
}

class Cat implements Animal {
    public void makeSound() {
        System.out.println("Cat meows...");
    }
}

现在,我们定义一个Filter来只扫描Animal及其子类:

import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.filter.AbstractClassTestingTypeFilter;
import org.springframework.core.type.filter.TypeFilter;

public class AssignableTypeFilter implements TypeFilter {
    private final Class<?> targetType;

    public AssignableTypeFilter(Class<?> targetType) {
        this.targetType = targetType;
    }

    @Override
    public boolean match(ClassMetadata metadata) {
        try {
            Class<?> clazz = Class.forName(metadata.getClassName());
            return targetType.isAssignableFrom(clazz);
        } catch (ClassNotFoundException e) {
            return false;
        }
    }
}

然后,在@ComponentScan注解中使用FilterType.ASSIGNABLE_TYPE过滤器:

@ComponentScan(basePackages = "com.example",
        includeFilters = {
            @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = Animal.class)
        })
public class MyApplication {
    // ...
}

在上述示例中,我们定义了一个AssignableTypeFilter类,实现了TypeFilter接口,并在match()方法中通过isAssignableFrom()方法判断待扫描的类是否是给定类型或其子类或实现类。

在@ComponentScan注解中使用@ComponentScan.Filter指定type为FilterType.ASSIGNABLE_TYPE,并将Animal类作为参数传入,这样在扫描时会过滤出Animal及其子类。

FilterType.ANNOTATION的过滤实现
@ComponentScan(value = "com.example",
    excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, 
        classes = {Controller.class, Service.class, Repository.class}),
    includeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION,
        classes = {CustomAnnotation.class}),
    useDefaultFilters = false)

在这段代码中,我们使用@ComponentScan注解来配置自动扫描的包路径和规则。

  1. 我们使用@ComponentScan注解的value属性来设置自动扫描的包路径,这里设置为"com.example"。

  2. 我们通过设置@ComponentScan注解的excludeFilters属性来排除某些类型的组件。使用@ComponentScan.Filter注解来指定需要排除的类型,其中type=ANNOTATION表示按照注解进行排除。具体的注解类如Controller、Service、Repository。

    • 同时,我们通过设置@ComponentScan注解的includeFilters属性来包含某些类型的组件。同样使用@ComponentScan.Filter注解来指定需要包含的类型,也是按照注解进行筛选。这里的例子中使用了自定义注解类CustomAnnotation。
  3. 我们通过设置@ComponentScan注解的useDefaultFilters=false来关闭Spring默认扫描全部的功能,使includeFilters生效。

FilterType.ANNOTATION的过滤实现
FilterType.CUSTOM的过滤实现

上面案例已经介绍了对应的type=ANNOTATION的案例,当使用FilterType.CUSTOM来进行过滤时,你需要自定义一个类来实现TypeFilter接口,然后根据自己的规则进行过滤。

以下是一个示例:

import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.filter.AbstractClassTestingTypeFilter;
import org.springframework.core.type.filter.TypeFilter;

public class CustomFilter implements TypeFilter {
    
    @Override
    public boolean match(ClassMetadata metadata) {
        // 在这里实现自定义的过滤逻辑
        // 返回 true 表示匹配成功,类将被扫描
        // 返回 false 表示匹配失败,类将被排除
        
        // 例如,只扫描带有"Service"字符串的类
        String className = metadata.getClassName();
        return className.contains("Service");
    }
}

然后,在@ComponentScan注解中使用自定义的过滤器:

@ComponentScan(basePackages = "com.example",
        excludeFilters = {
            @ComponentScan.Filter(type = FilterType.CUSTOM, classes = CustomFilter.class)
        })
public class MyApplication {
    // ...
}

在上述示例中,我们定义了一个CustomFilter类,实现了TypeFilter接口,并在match()方法中实现了自定义的过滤逻辑。在这个示例中,我们只会扫描带有"Service"字符串的类,排除其他类。在@ComponentScan注解中使用@ComponentScan.Filter指定type为FilterType.CUSTOM,并将CustomFilter类作为参数传入,这样在扫描时会应用我们定义的自定义过滤器来进行过滤。

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

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

相关文章

【广州华锐互动】VR安防网络综合布线仿真实训打造沉浸式的教学体验

随着科技的快速发展&#xff0c;综合布线技术在建筑、数据中心、网络基础设施等领域的应用越来越广泛。为了适应这一趋势&#xff0c;传统的教学方法已经无法满足现代教育的需求。因此&#xff0c;采用创新的教学手段&#xff0c;如虚拟现实&#xff08;VR&#xff09;技术&…

自动化测试框架 —— pytest框架入门篇

今天就给大家说一说pytest框架。 今天这篇文章呢&#xff0c;会从以下几个方面来介绍&#xff1a; 1、首先介绍一下pytest框架 2、带大家安装Pytest框架 3、使用pytest框架时需要注意的点 4、pytest的运行方式 5、pytest框架中常用的插件 01、pytest框架介绍 pytest 是 pytho…

办公工具使用技巧汇总

总结下在使用办公工具时的一些技巧 1.word中自动排序 例如在表格中插入序号&#xff0c;如下图。有时候数据量较大时&#xff0c;一个一个的手动输入&#xff0c;效率不高&#xff0c;需要一种快捷的方式进行序号填充。 初级版本&#xff1a; 选择需要填写序号的列-开始工具…

从系统层到应用层,vivo 已在安全生态层

你每隔多久就会使用一次手机&#xff1f;调研结果也许会让你大吃一惊。 权威报告数据显示&#xff0c;2022年&#xff0c;24.9%的受访者每日使用手机时长超过10小时&#xff0c;其中3.8%的受访者“机不离手”&#xff0c;每日使用时长超过15小时。而真正让手机化身为时间吞金兽…

黑豹程序员-架构师学习路线图-百科:Knife4j API接口文档管理

文章目录 由来&#xff1a;接口文档第一代&#xff1a;Swagger第二代&#xff1a;Knife4j界面 由来&#xff1a;接口文档 古老编程是一个语言前后端通吃&#xff0c;ASP、JSP、PHP都是如此。 但随着项目规模变大&#xff0c;项目团队也开始壮大&#xff0c;岗位职责开始细分&a…

使用Redis实现文章阅读量、收藏、点赞数量记录功能

目录 一、前言二、业务分析三、Redis数据结构选择分析和实现3.1、三个数据缓存都分别使用 字符串 结构计数器存储对应数量值3.2、三个数据缓存使用一个 Hash 结构存储3.3、阅读量使用字符串结构计算器&#xff0c;收藏和点赞分别使用 Set 集合存储 四、总结 一、前言 在博客中会…

HCIA-PPPOE原理与配置

PPPOE原理与配置 实验拓扑图实现步骤家庭网关 AR201PPPOE客户端&#xff08; ISP光猫&#xff09;PPPOE服务器&#xff08;ISP路由器&#xff09; 实验拓扑图 实现步骤 家庭网关 AR201 E0/0/0-7为LAN口&#xff08;二层接口&#xff09;E0/0/8为WAN口&#xff08;三层接口&am…

【每日一题】2258. 逃离火灾-2023.11.9

题目&#xff1a; 2258. 逃离火灾 给你一个下标从 0 开始大小为 m x n 的二维整数数组 grid &#xff0c;它表示一个网格图。每个格子为下面 3 个值之一&#xff1a; 0 表示草地。1 表示着火的格子。2 表示一座墙&#xff0c;你跟火都不能通过这个格子。 一开始你在最左上角…

LeetCode【78. 子集】

78. 子集 中等 2.2K 相关企业 给你一个整数数组 nums &#xff0c;数组中的元素 互不相同 。返回该数组所有可能的子集&#xff08;幂集&#xff09;。 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&…

Frp内网穿透部署

Frp内网穿透部署记录windows为例 A固定外网IP服务器一台&#xff08;可以映射端口&#xff09;B内网PC一台&#xff0c;可上外网 A固定外网IP服务器一台&#xff08;可以映射端口&#xff09; B内网PC一台&#xff0c;可上外网 GO语言&#xff1a;https://golang.org/doc/ins…

如何用CHAT 写会后总结

问CHAT&#xff1a;阐述参加IMS系统培训课程的收益和不学的损失。 CHAT 回复&#xff1a; 参加IMS系统培训课程的收益&#xff1a; 1. 提升技能和知识&#xff1a;通过参加IMS系统培训课程&#xff0c;你可以学习到刚新的信息技术和知识&#xff0c;增强你的技能和经验&…

UART编程(寄存器)

1. 串口编程步骤 1.1 看原理图确定引脚 有很多串口&#xff0c;使用哪一个&#xff1f;看原理图确定 1.2 配置引脚为UART功能 至少用到发送、接收引脚&#xff1a;txd、rxd 需要把这些引脚配置为UART功能&#xff0c;并使能UART模块 1.3 设置串口参数 有哪些参数&#xf…

Leecode刷题【hot100】盛最多水的容器

给定一个长度为 n 的整数数组 height 。有 n 条垂线&#xff0c;第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线&#xff0c;使得它们与 x 轴共同构成的容器可以容纳最多的水。 返回容器可以储存的最大水量。 说明&#xff1a;你不能倾斜容器。 示例…

linux生成code文件

1. 设置core文件路径在当前工作目录 echo "core-%e-%p-%t" > /proc/sys/kernel/core_pattern 具体参数 %s - insert signal that caused the coredump into the filename 添加导致产生core的信号 %t - insert UNIX time that the coredump occurred into filen…

使用 Wireshark 抓包工具快速分析 IoT 物联网终端设备的网络通信行为

当你进行 IoT 物联网开发过程中&#xff0c;终端-MQTT 服务器-业务系统-App 全链路联调时往往难以快速定位问题&#xff1a;终端可能未正常发出消息报文&#xff0c;也可能在网络传输中丢失&#xff0c;也可能被 MQTT 服务器限流丢弃&#xff0c;或者业务系统处理异常而丢失。此…

Centos7安装宝塔面板8.0.3并实现公网远程登录宝塔面板【内网穿透】

Centos7安装宝塔面板8.0.3并实现公网远程登录宝塔面板【内网穿透】 文章目录 Centos7安装宝塔面板8.0.3并实现公网远程登录宝塔面板【内网穿透】一、使用官网一键安装命令安装宝塔二、简单配置宝塔&#xff0c;内网穿透三、使用固定公网地址访问宝塔 宝塔面板作为建站运维工具&…

flink1.18.0 sql-client报错

报错 Flink SQL> select * from t1; [ERROR] Could not execute SQL statement. Reason: org.apache.flink.table.api.ValidationException: Could not find any factory for identifier kafka that implements org.apache.flink.table.factories.DynamicTableFactory in t…

如何搭建一个自定义UI框架的Playground(一)

文章目录 初衷需求技术选型详细设计&#xff08;一&#xff09;1.业务设计2.交互设计3.程序设计3.1 游戏生命周期设计3.2 UI界面管理设计 初衷 想要比较系统、深入地了解游戏UI框架的设计与开发&#xff0c;就需要自己实践去开发一个可以预览的UI项目&#xff0c;但是目前没有…

OpenTiny Vue 组件库支持 Vue2.7 啦!

之前 OpenTiny 发布了一篇 Vue2 升级 Vue3 的文章。 &#x1f596;少年&#xff0c;该升级 Vue3 了&#xff01; 里面提到使用了 ElementUI 的 Vue2 项目&#xff0c;可以通过 TinyVue 和 gogocode 快速升级到 Vue3 项目。 有朋友评论替换button出错了&#xff0c;并且贴出了…

K8S篇之etcd数据备份与恢复

一、etcd备份与恢复 基本了解&#xff1a; 1、k8s 使用etcd数据库实时存储集群中的数据&#xff0c;安全起见&#xff0c;一定要备份。 2、备份只需要在一个节点上备份就可以了&#xff0c;每个节点上的数据是同步的&#xff1b;但是数据恢复是需要在每个节点上进行。 3、etcd…