# springboot-task2 **Repository Path**: kirayous/springboot-task2 ## Basic Information - **Project Name**: springboot-task2 - **Description**: task2 - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-04-20 - **Last Updated**: 2021-04-27 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 实验二 利用Spring boot的自动装配特性实现动态注册组件 ## 一、 实验目的 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 initialize ![输入图片说明](https://images.gitee.com/uploads/images/2021/0427/090619_dea78722_5631448.png "屏幕截图.png") 注意:创建项目时,请选择添加 Spring Configuration Processor 依赖。 ![输入图片说明](https://images.gitee.com/uploads/images/2021/0427/090734_47be3e24_5631448.png "屏幕截图.png") ![输入图片说明](https://images.gitee.com/uploads/images/2021/0427/090940_b42773ec_5631448.png "屏幕截图.png") #### 2、 创建一个自定义的CommandLineRunner接口的实现类。 注意:不要在自定义类上加@Component注解。 #### 3、 创建一个自定义的自动配置类。 ![输入图片说明](https://images.gitee.com/uploads/images/2021/0427/102009_49559c51_5631448.png "屏幕截图.png") #### 4、 创建spring.factories文件 ![输入图片说明](https://images.gitee.com/uploads/images/2021/0427/104824_5603cf23_5631448.png "屏幕截图.png") 注意:当创建一个文本文件时,idea会访问文本文件的访问类型,按上图选择。 注意:spring.factories必须放在META-INF目录下。 说明:按上图输入内容。key必须是EnableAutoConfiguration的全限定类名,值为刚才我们自定义的自动配置类的全限定类路径的类名。 ![输入图片说明](https://images.gitee.com/uploads/images/2021/0427/105500_78350211_5631448.png "屏幕截图.png") 测试运行程序: ![输入图片说明](https://images.gitee.com/uploads/images/2021/0427/105115_b7b19265_5631448.png "屏幕截图.png") 运行结果: ![输入图片说明](https://images.gitee.com/uploads/images/2021/0427/105612_f910c89c_5631448.png "屏幕截图.png") 解决中文乱码问题: ![输入图片说明](https://images.gitee.com/uploads/images/2021/0427/105805_d4b5aff4_5631448.png "屏幕截图.png") ![输入图片说明](https://images.gitee.com/uploads/images/2021/0427/105835_74c8cbd4_5631448.png "屏幕截图.png") 由上图可知,我们自定义的自动配置类已经生效。 #### 5、 给自动配置类添加有效条件。 步骤如下: 1) 利用 @ConditionalOnProperty 注解,添加属性条件。 ![输入图片说明](https://images.gitee.com/uploads/images/2021/0427/110912_6170410a_5631448.png "屏幕截图.png") 2) 在application.properties属性文件中添加一个自定义的属性。 ![输入图片说明](https://images.gitee.com/uploads/images/2021/0427/110406_726a902b_5631448.png "屏幕截图.png") 3) 切换属性值false/true,观察终端的显示,判断自动装配的配置类是否生效。 ![输入图片说明](https://images.gitee.com/uploads/images/2021/0427/110410_f8765795_5631448.png "屏幕截图.png") ![输入图片说明](https://images.gitee.com/uploads/images/2021/0427/110458_9146ba5a_5631448.png "屏幕截图.png") 总结: 通过@ConditionalOnProperty可以控制配置类是否生效,可以将配置与代码进行分离,实现了更好的控制配置. @ConditionalOnProperty实现是通过havingValue与配置文件中的值对比,返回为true则配置类生效,反之失效. #### 6、 自定义的一个Bean,绑定属性值,并生成spring配置类的元数据文件。 步骤如下: 1) 创建一个类,并在类上加@ConfigurationProperties注解,设置注解的prefix属性指定绑定的属性的前缀。 ![输入图片说明](https://images.gitee.com/uploads/images/2021/0427/111501_b65a4b03_5631448.png "屏幕截图.png") 2) 在某个配置类上添加@EnableConfigurationProperties,并指定装配的属性Bean。 ![输入图片说明](https://images.gitee.com/uploads/images/2021/0427/111428_ca0e1eea_5631448.png "屏幕截图.png") 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依赖: ![输入图片说明](https://images.gitee.com/uploads/images/2021/0427/111643_e8643474_5631448.png "屏幕截图.png") b. 编译打包项目。观察target目录下的元数据文件: ![输入图片说明](https://images.gitee.com/uploads/images/2021/0427/112046_93746699_5631448.png "屏幕截图.png") c. 现在我们再回去编辑属性文件时,只要输入属性的部分关键字,idea会自动提示,如下图: ![输入图片说明](https://images.gitee.com/uploads/images/2021/0427/112114_5ab807c6_5631448.png "屏幕截图.png") 推荐阅读:配置元数据官方文档 #### 7、 根据阅读框架源码,我们可以自定义一个事件发布器,并设置线程池,实现异步发布事件。 注意:这个自定义的事件发布器的Bean的名称必须是“applicationEventMulticaster”。 源码如下图: ![输入图片说明](https://images.gitee.com/uploads/images/2021/0427/114207_3e6841fb_5631448.png "屏幕截图.png") a. 自定义的事件发布器: ![输入图片说明](https://images.gitee.com/uploads/images/2021/0427/114137_f874ddde_5631448.png "屏幕截图.png") b. 自定义事件类。 ![输入图片说明](https://images.gitee.com/uploads/images/2021/0427/114938_7054108d_5631448.png "屏幕截图.png") c. 自定义事件监听器。 ![输入图片说明](https://images.gitee.com/uploads/images/2021/0427/114947_f4a5c35f_5631448.png "屏幕截图.png") d. 编写一个测试用例,检查发布事件时,是否使用了多线程异步处理。 ![输入图片说明](https://images.gitee.com/uploads/images/2021/0427/114902_1b02789f_5631448.png "屏幕截图.png") 运行单元测试结果如下: ![输入图片说明](https://images.gitee.com/uploads/images/2021/0427/114838_948b0431_5631448.png "屏幕截图.png") #### 8、 自定义 ApplicationReadyEvent 的事件监听器。( 2020年10月新增 ) a. 根据SpringApplication.run方法的源码分析,当spring boot执行完所有的启动流程后,会发布 ApplicationReadyEvent 事件。 b. 从run方法源码可知,发布ApplicationReadyEvent的时间是在回调 CommandLineRunner之后。 c. 尝试自定义一个ApplicationReadyEvent的事件监听器,并在终端输出指定信息,确定是在CommandLineRunner的输出信息之后。 自定义的ApplicationReadyEvent监听器: ![输入图片说明](https://images.gitee.com/uploads/images/2021/0427/115415_240eeb3b_5631448.png "屏幕截图.png") 运行结果: ![输入图片说明](https://images.gitee.com/uploads/images/2021/0427/115336_46fdef18_5631448.png "屏幕截图.png") 深入思考: 在上面的例子中,我们使用了Spring Boot框架提供的默认线程池。默认线程池在自动配置类TaskExecutionAutoConfiguration中定义。我们可以自定义一个自己的线程池,这样可以配置更多的属性。尝试一下自定义一个线程池,然后给自定义的事件发布器使用。