SpringBoot第二天

Bean管理

Bean扫描

在Spring中,Bean的扫描有两种写法

第一种是在xml配置文件中用标签扫描

<context:component-scan basepackage="com.cacb"/>

第二种是是注解扫描

@ComponentScan(basePackages="com.cacb")

 而在SpringBoot中,我们在启动类中使用了

@SpringBootApplication

注解,该注解实际上包含如下注解

故只要调用该注解Spring就能扫描启动类所在的包及其子包中的Bean,在我们使用时就实现了自动扫描,同时我们也应注意所有的Bean应该放在启动类所在的包及其子包中。

Bean注册

如果要注册的Bean来自第三方(不是自定义的),是无法使用@Component及衍生注解声明Bean的,可以使用如下两个注解

@Bean

譬如,我们在一个jar包中有一个实体类Book,需要在当前工程中导入Book实体,首先我们就需要在启动类中使用@Bean注解来注入Book对象

@SpringBootApplication
public class SpringBootMybatisApplication {public static void main(String[] args) {SpringApplication.run(SpringBootMybatisApplication.class, args);}@Beanpublic Book book(){return new Book();}}

但是这种方法需要在启动类中注解,不推荐,更好的方法是单独创建一个配置类来集中管理注册第三方Bean,该配置类需要在启动类同一个包及其子包中,并且要有@Configuration注解

@Configuration
public class CommonConfig {@Beanpublic Book book(){return new Book();}
}

如果需要改名,例如,要将Book对象名改为user,可以在Bean注释后更改(默认对象名为方法名):

    @Bean("user")public Book book(){return new Book();}

如果一个第三方对象内需要注入另一个第三方对象,可以在参数内自动注入,如下例在BookStore中注入Book:

    @Beanpublic Book book(){return new Book();}@Beanpublic BookStore bookstore(Book book){return new BookStore();}

@Import 

导入配置类

 例如,上文所写的CommonConfig不与启动类放在同一个包中,启动类就无法自动扫描到该配置类,此时就需要在启动类中使用@Import来完成手动注解

@SpringBootApplication
@Import(CommonConfig.class)
public class SpringBootMybatisApplication {public static void main(String[] args) {SpringApplication.run(SpringBootMybatisApplication.class, args);}}

注:如果有多个配置类需要注解,可以使用{}数组的形式来完成注解,同时,也可以通过导入ImportSelector接口来完成该工作。 

导入ImportSelector接口实现类

例如此时,config文件与启动类不在同一个文件,我们也可以通过导入ImportSelector接口实现类来手动注解。

首先我们需要制作一个ImportSelector接口实现类

public class CommonImportSelector implements ImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {return new String[]{"com.cacb.config.CommonConfig"};}
}

然后再去启动类中使用@Import注解来完成手动注解

@SpringBootApplication
@Import(CommonImportSelector.class)
public class SpringBootMybatisApplication {public static void main(String[] args) {SpringApplication.run(SpringBootMybatisApplication.class, args);}}

当然,需要注入的Bean一般是从配置文件中读取的,方法如下,先构建配置文件 

 注:每行指书写一个Bean的全类名

com.cacb.config.CommonConfig

然后去接口实现类中加载配置文件

public class CommonImportSelector implements ImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {List<String> imports = new ArrayList<>();InputStream is = CommonImportSelector.class.getClassLoader().getResourceAsStream("common.imports");BufferedReader br = new BufferedReader(new InputStreamReader(is));String line = null;try {while ((line = br.readLine()) != null){imports.add(line);}} catch (IOException e){throw new RuntimeException(e);} finally {if(br != null){try {br.close();} catch (IOException e){throw new RuntimeException(e);}}}return imports.toArray(new String[0]);}
}

 组合类注解@EnableXxxx注解封装@Import注解

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Import(CommonImportSelector.class)
public @interface EnableCommonConfig {
}

完成后就可以在启动类中使用@EnableCommonConfig注解来代替@Import注解使用

@SpringBootApplication
@EnableCommonConfig
public class SpringBootMybatisApplication {

注册条件

SpringBoot提供了设置注册生效条件的注解@Conditional

自动配置原理 

自动配置

遵循约定大于配置的原则,在boot程序启动后,起步依赖中的一些Bean对象会自动注入到IOC容器

程序引入spring-boot-starter-web起步依赖,启动后,会自动往IOC容器中注入DispatcherServlet

在主启动类上添加了SpringBootApplication注解,这个注解组合了EnableAutoConfiguration注解

EnableAutoConfiguration注解又组合了Import注解,导入了AutoConfigurationImportSelector类

实现selectImports方法,这个方法经过多层调用,最终会读取META-INF目录下的后缀名为imports的文件,boot2.7以前的版本读取的是spring.factories文件

读取到imports文件中的全类名之后,会解析注册条件,也就是@Conditional及其衍生注解,把满足注册条件的Bean对象自动注入到IOC容器中

自定义starter

以Mybatisstarter为例

我们需要构建两个模块

在自动配置模块中首先要导入相应依赖坐标

  <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><version>3.2.2</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jdbc</artifactId><version>3.0.0</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.14</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>3.8.1</version><scope>test</scope></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>3.0.3</version><scope>compile</scope></dependency></dependencies>

然后提供自动配置类

@AutoConfiguration
public class MyBatisAutoConfig {@Beanpublic SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();sqlSessionFactoryBean.setDataSource(dataSource);return sqlSessionFactoryBean;}@Beanpublic MapperScannerConfigurer mapperScannerConfigurer(BeanFactory beanFactory){MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();//扫描的包:启动类所在的包及其子包List<String> packages =  AutoConfigurationPackages.get(beanFactory);String p = packages.get(0);mapperScannerConfigurer.setBasePackage(p);//扫描的注解mapperScannerConfigurer.setAnnotationClass(Mapper.class);return mapperScannerConfigurer;}
}

自建import文件,并将自动配置类完整路径写入

 注意imports文件存储路径一定要在META-INF.spring下

com.cacb.config.MyBatisAutoConfig

下面开始配置stater模块,该模块只需要导入相应坐标,故src文件可以直接删除掉

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><version>3.2.2</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jdbc</artifactId><version>3.0.0</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.14</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>3.8.1</version><scope>test</scope></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>3.0.3</version><scope>compile</scope></dependency></dependencies>

最重要的是导入我们写的自动装配模块,最好也要将自装配模块所依赖的坐标一并导入 

 

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

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

相关文章

Stable Diffusion 模型下载:EnvyHyperrealXL01

模型介绍 一个基于 EnvyHyperdrive 和 NewReality 的超写实模型&#xff0c;使生成的照片级真实感模型在主题和视觉上与我的其他模型相似&#xff0c;除了&#xff0c;你知道&#xff0c;照片级真实感。 &#x1f603; 条目内容类型大模型基础模型SDXL 1.0来源CIVITAI作者_En…

《Python 网络爬虫简易速速上手小册》第5章:Python 数据存储与管理(2024 最新版)

文章目录 5.1 选择数据存储方案5.1.1 重点基础知识讲解5.1.2 重点案例&#xff1a;使用 SQLite 存储博客文章数据5.1.3 拓展案例 1&#xff1a;使用 MongoDB 存储社交媒体动态5.1.4 拓展案例 2&#xff1a;使用 Elasticsearch 存储和检索日志数据 5.2 数据清洗与预处理5.2.1 重…

【动态规划】【树形dp】【C++算法】968监控二叉树

作者推荐 【动态规划】【字符串】【表达式】2019. 解出数学表达式的学生分数 本文涉及知识点 动态规划汇总 LeetCode:968监控二叉树 给定一个二叉树&#xff0c;我们在树的节点上安装摄像头。 节点上的每个摄影头都可以监视其父对象、自身及其直接子对象。 计算监控树的所…

springcloud-gateway升级版本allowedOrigins要改allowedOriginPatterns

前言 报错: java.lang.IllegalArgumentException: When allowCredentials is true,allowedOrigins cannot contain the special value "*"since that cannot be set on the "Access-Control-Allow-Origin"response header. To allow credentials to a se…

计算机网络_1.6.3 计算机网络体系结构分层思想举例

1.6.3 计算机网络体系结构分层思想举例 1、实例引入&#xff08;用户在主机中使用浏览器访问web服务器&#xff09;2、从五层原理体系结构的角度研究该实例3、练习题 笔记来源&#xff1a; B站 《深入浅出计算机网络》课程 本节通过一个常见的网络应用实例&#xff0c;来介绍计…

解决Android camera 录像中拍照帧率不足30fps

问题现象 camera录像中拍照&#xff0c;录出来的视频帧率为29.3fps&#xff0c;未达到30fps。 问题分析 这个场景相当于跑了previevediocapture&#xff0c;极其损耗性能。 当前场景CPU频率已处于最高。 抓取systrace分析。 1&#xff0c;分析掉帧直接原因 SinkNode存在大…

四、Redis之配置文件

redis配置文件的名称 redis.conf 通过命令 find / -name redis.confvim redis.conf通过 : set nu 设置行号: set nonu 取消行号/关键字 搜索关键字: set noh 取消高亮选择4.1 Units 配置大小单位&#xff0c;开头定义了一些基本的度量单位&#xff0c;只支持 bytes&#…

《Vue3 基础知识》 使用 GoGoCod 升级到Vue3+ElementPlus 适配处理

此篇为 《Vue2ElementUI 自动转 Vue3ElementPlus&#xff08;GoGoCode&#xff09;》 的扩展&#xff01; Vue3 适配 Vue3 不兼容适配 Vue 3 迁移指南 在此&#xff0c;本章只讲述项目或组件库中遇到的问题&#xff1b; Vue3 移除 o n &#xff0c; on&#xff0c; on&#…

海量数据处理商用短链接生成器平台 - 2

第二章 短链平台项目创建git代码管理开发分层规范 第1集 短链平台实战-Maven聚合工程创建微服务项目 **简介&#xff1a;Maven聚合工程创建微服务项目实战 ** Maven聚合工程拆分 dcloud-common 公共依赖包 dcloud-app FlinkKafka实时计算 dcloud-account 账号流量包微服务 dc…

如何在Vue应用程序中使用Vue-Router来实现路由嵌套动画效果

Vue-Router是Vue.js官方的路由管理插件&#xff0c;可以帮助我们轻松管理应用程序的路由。除了基本的路由功能外&#xff0c;Vue-Router还允许我们在切换路由时添加动画效果&#xff0c;提升用户体验。本文将介绍如何使用Vue-Router来实现路由嵌套动画效果&#xff0c;并提供具…

为什么越来越多的企业在考虑将ERP从云端迁移到本地?

越来越多的企业在考虑将核心ERP迁移到本地部署&#xff0c;原来实施的时候局限于业务规模、实施成本的原因采用云端部署的方式越来越不再适应于企业规模的发展、系统应用和数据安全的要求。 因此他们都宁愿将云端ERP的数据迁移到本地&#xff0c;使得系统数据和安全更加可控。…

python中[[]] * (n)和[[] for _ in range(n)]的区别

1、现象 刷leetcode207的时候碰到一个坑&#xff0c;用[[]] * (n)初始化二维数组&#xff0c;逻辑是正确的&#xff0c;但是结果始终不对。 2、原因 最后定位是初始化语句使用错误导致的&#xff0c;我使用的是[[]] * (n)&#xff0c;应该使用[[] for _ in range(n)] 3、解…