# test2 **Repository Path**: yu-zhiguang/test2 ## Basic Information - **Project Name**: test2 - **Description**: 实验二 利用Spring boot的自动装配特性实现动态注册组件 - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-04-13 - **Last Updated**: 2021-07-06 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ### 实验二 利用Spring boot的自动装配特性实现动态注册组件
课程名称:企业级开发框架实践          学期:2021年春季
实验名称 利用Spring boot的自动装配特性实现动态注册组件 实验序号
姓名 余致光 学号 201841412125 班级 18软卓1班
实验地点 8B409 实验日期 2021.04.13 指导老师 黎志雄
教师评语 实验成绩 评阅老师
百分制
同班同学
#### 一、实验目的 1. 掌握Spring Boot的自动配置原理; 2. 掌握Spring框架动态注册Bean的原理; 3. 掌握自动生成元数据文件。 4. 掌握Spring框架的事件模型。 #### 二、实验环境 1. JDK 1.8或更高版本 2. Maven 3.6+ 3. IntelliJ IDEA #### 三、实验任务 1. 通过IntelliJ IDEA的Spring Initializr向导创建Spring Boot项目。 注意:创建项目时,请选择添加 **Spring Configuration Processor** 依赖。 2. 创建一个自定义的CommandLineRunner接口的实现类。 注意:不要在自定义类上加@Component注解。 3. 创建一个自定义的自动配置类。 4. 创建spring.factories文件 注意:当创建一个文本文件时,idea会访问文本文件的访问类型,按上图选择。 注意:spring.factorie**必须放在META-INF目录下**。 说明:按上图输入内容。key必须是EnableAutoConfiguration的全限定类名,值为刚才我们自定义的自动配置类的全限定类路径的类名。 5. 给自动配置类添加有效条件。 步骤如下: 1)利用 **@ConditionalOnProperty** 注解,添加属性条件。 2)在application.properties属性文件中添加一个自定义的属性。 3)切换属性值false/true,观察终端的显示,判断自动装配的配置类是否生效。 6. 自定义的一个Bean,绑定属性值,并生成spring配置类的元数据文件。 步骤如下: 1)创建一个类,并在类上加@ConfigurationProperties注解,设置注解的prefix属性指定绑定的属性的前缀。 2)在某个配置类上添加@EnableConfigurationProperties,并指定装配的属性Bean。 3)使用spring boot框架提供的注解处理器生成自定义属性的元数据文件。 ``` 说明: Spring Boot应程序打包后的jar文件中包含元数据文件,这些文件提供了所有受支持的配置属性的详细信息。这些文件旨在让IDE开发人员在编辑application.properties或application.yml文件时提供上下文帮助和“代码完成” 。Interllj IDEA默认支持。 元数据文件位于META-INF目录下,名字spring-configuration-metadata.json。 元数据文件可以自己写,或使用spring boot官方提供的依赖包自动生成。 在pom.xml文件中引入spring-boot-configuration-processor依赖。这个依赖包里有spring boot提供的注解处理器,在项目编译时检查项目内所有@ConfigurationProperties的类,并生成元数据文件。 ``` a. 在pom.xml文件中引入spring-boot-configuration-processor依赖: b. 编译打包项目。观察target目录下的元数据文件: c. 现在我们再回去编辑属性文件时,只要输入属性的部分关键字,idea会自动提示,如下图: 7. 根据阅读框架源码,我们可以自定义一个事件发布器,并设置线程池,实现异步发布事件。 **注意**:这个自定义的事件发布器的Bean的名称必须是“**applicationEventMulticaster**”。 ​ a. 自定义的事件发布器: ​ b.自定义事件类。 ​ c.自定义事件监听器。 ​ d.编写一个测试用例,检查发布事件时,是否使用了多线程异步处理。 8. 自定义 ApplicationReadyEvent 的事件监听器。( 2020年10月新增 ) a. 根据SpringApplication.run方法的源码分析,当spring boot执行完所有的启动流程后,会发布 **ApplicationReadyEvent** 事件。 b.从run方法源码可知,发布ApplicationReadyEvent的时间是在回调 CommandLineRunner之后。 c.尝试自定义一个ApplicationReadyEvent的事件监听器,并在终端输出指定信息,确定是在CommandLineRunner的输出信息之后。 ``` 深入思考: 在上面的例子中,我们使用了Spring Boot框架提供的默认线程池。默认线程池在自动配置类TaskExecutionAutoConfiguration中定义。我们可以自定义一个自己的线程池,这样可以配置更多的属性。尝试一下自定义一个线程池,然后给自定义的事件发布器使用。 ``` #### 四、实验结果 1. 通过IntelliJ IDEA的Spring Initializr向导创建Spring Boot项目。 ![1-1](https://images.gitee.com/uploads/images/2021/0423/161858_0ac859cd_8879583.png "屏幕截图.png") ![1-2](https://images.gitee.com/uploads/images/2021/0423/161932_9f75e5bf_8879583.png "屏幕截图.png") 2. 创建一个自定义的CommandLineRunner接口的实现类。 ![2-1](https://images.gitee.com/uploads/images/2021/0423/162156_4512d9e4_8879583.png "屏幕截图.png") 3. 创建一个自定义的自动配置类。 ![3-1](https://images.gitee.com/uploads/images/2021/0423/165915_5857d9f0_8879583.png "屏幕截图.png") 4. 创建spring.factories文件 ![4-1](https://images.gitee.com/uploads/images/2021/0423/162610_c0ee3e02_8879583.png "屏幕截图.png") ![4-2](https://images.gitee.com/uploads/images/2021/0423/162657_4fcaf5c1_8879583.png "屏幕截图.png") ![4-3](https://images.gitee.com/uploads/images/2021/0423/162745_b5d78926_8879583.png "屏幕截图.png") ![4-4](https://images.gitee.com/uploads/images/2021/0423/163708_1c0cdddc_8879583.png "屏幕截图.png") ![4-5](https://images.gitee.com/uploads/images/2021/0423/163759_2ddd49e5_8879583.png "屏幕截图.png") 5. 给自动配置类添加有效条件。 ![5-1](https://images.gitee.com/uploads/images/2021/0423/165955_ce1df78e_8879583.png "屏幕截图.png") ![5-2](https://images.gitee.com/uploads/images/2021/0423/164542_88872659_8879583.png "屏幕截图.png") 当属性值为true,自动装配的配置类生效,如下: ![5-3](https://images.gitee.com/uploads/images/2021/0423/164858_67fb2103_8879583.png "屏幕截图.png") 当属性值为false,自动装配的配置类不生效,如下: ![5-4](https://images.gitee.com/uploads/images/2021/0423/164953_c7a3443b_8879583.png "屏幕截图.png") 6. 自定义的一个Bean,绑定属性值,并生成spring配置类的元数据文件。 1)创建一个类,并在类上加@ConfigurationProperties注解,设置注解的prefix属性指定绑定的属性的前缀。 ![6-1](https://images.gitee.com/uploads/images/2021/0423/165704_25db4f65_8879583.png "屏幕截图.png") 2)在某个配置类上添加@EnableConfigurationProperties,并指定装配的属性Bean。 ![6-2](https://images.gitee.com/uploads/images/2021/0423/165816_ecca214e_8879583.png "屏幕截图.png") 3)使用spring boot框架提供的注解处理器生成自定义属性的元数据文件。 ​ a. 在pom.xml文件中引入spring-boot-configuration-processor依赖: ![6-3-a](https://images.gitee.com/uploads/images/2021/0423/170427_a7e1949a_8879583.png "屏幕截图.png") ​ b. 编译打包项目(compile->package)。观察target目录下的元数据文件: ![6-3-b](https://images.gitee.com/uploads/images/2021/0423/170720_f0e71569_8879583.png "屏幕截图.png") ​ c. 现在我们再回去编辑属性文件时,只要输入属性的部分关键字,idea会自动提示,如下图: ![6-3-c](https://images.gitee.com/uploads/images/2021/0423/170926_de62e544_8879583.png "屏幕截图.png") 7. 根据阅读框架源码,我们可以自定义一个事件发布器,并设置线程池,实现异步发布事件。 ​ a. 自定义的事件发布器: ![7-a](https://images.gitee.com/uploads/images/2021/0423/171209_02cb47ff_8879583.png "屏幕截图.png") ​ b.自定义事件类。 ![7-b](https://images.gitee.com/uploads/images/2021/0423/171104_99023791_8879583.png "屏幕截图.png") ​ c.自定义事件监听器。 ![7-c](https://images.gitee.com/uploads/images/2021/0423/171307_5776bf48_8879583.png "屏幕截图.png") ​ d.编写一个测试用例,检查发布事件时,是否使用了多线程异步处理。 ![7-d](https://images.gitee.com/uploads/images/2021/0423/171357_e52e1132_8879583.png "屏幕截图.png") 运行单元测试结果如下: ![7-e](https://images.gitee.com/uploads/images/2021/0423/171626_be21f9ae_8879583.png "屏幕截图.png") 8. 自定义 ApplicationReadyEvent 的事件监听器。 ​ a. 根据SpringApplication.run方法的源码分析,当spring boot执行完所有的启动流程后,会发布 **ApplicationReadyEvent** 事件。 ![8-a-1](https://images.gitee.com/uploads/images/2021/0423/172013_22cb5fd5_8879583.png "屏幕截图.png") ![8-a-2](https://images.gitee.com/uploads/images/2021/0423/171739_f5b1ebc9_8879583.png "屏幕截图.png") ​ b.从run方法源码可知,发布ApplicationReadyEvent的时间是在回调CommandLineRunner之后。 ![8-b](https://images.gitee.com/uploads/images/2021/0423/172113_da1002fc_8879583.png "屏幕截图.png") ​ c.尝试自定义一个ApplicationReadyEvent的事件监听器,并在终端输出指定信息,确定是在CommandLineRunner的输出信息之后。 ![8-c](https://images.gitee.com/uploads/images/2021/0423/172831_4fcb9516_8879583.png "屏幕截图.png")