# springboot-experiment2 **Repository Path**: lirisheng/springboot-experiment2 ## Basic Information - **Project Name**: springboot-experiment2 - **Description**: 利用Spring boot 的自动装配特性实现动态注册组件 - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-04-13 - **Last Updated**: 2020-12-20 ## 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) 自定义配置类,并配置相应的配置元数据 2) 自定义一个事件发布器 3) 自定义一个线程池 ### 四.实验步骤及结果 1) **自定义配置类,并配置相应的配置元数据** * **核心:其实Spring boot在启动时实现自动配置,原理上就是把自动配置类作为bean注入到Spring container中,然后在合适的情况下这些自动配置的bean起作用** * **如何添加自定义的自动配置** 步骤: 1) 编写一个自定义要配置的类 ```java public class HelloConfig { public HelloConfig(){ System.out.println("自定义的HelloConfig自动配置起作用"); } } ``` 2) 编写配置的类,实现上面的类的自动配置功能 ```java package com.lirisheng.experiment.autoConfig; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; public class AutoConfig { @Bean HelloConfig helloConfig(){ return new HelloConfig(); } } ``` 3) 使上面的配置类起作用,即在项目中的`resources`目录下创建一个META-INF文件夹,再在该文件夹下创建`spring.factories`文件,该文件的内容如下 ``` //注意该key一定是EnableAutoConfiguration,因为跟Spring boot默认的spring.factories里面的key一样 org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.lirisheng.experiment.autoConfig.AutoConfig ``` 4) 运行具有`@SpringBootApplication`类,查看自动配置的类是否起自动
* **如果我们有条件使自动配置类起作用(即注入到container中)** 步骤 1) 就是在`AutoConfig`类中利用`@ConditionalOnProperty`注解实现即可,代码如下 ```java package com.lirisheng.experiment.autoConfig; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; @EnableConfigurationProperties(CustomProperties.class) public class AutoConfig { @Bean @ConditionalOnProperty(prefix = "lirisheng.auto",name = "enable",havingValue = "true") HelloConfig helloConfig(){ return new HelloConfig(); } } ``` 2) 运行@SpringBootApplication类,运行结果如下
3) 在`application.properties`中配置如下信息,使其生效 ```java lirisheng.auto.enable=true ``` 4) 再次运行结果
* **如何为自动配置类添加配置元数据** * 方法一:元数据文件可以自己手写 * 方法二:可以使用spring boot官方提供的依赖包自动生成 1) 原理:该依赖包李有spring boot提供的注解处理器,在项目编译是检查项目内所有的@ConfigurationProperties的类,并生成元数据文件 2) 步骤: 1) 在pom.xml文件中引入`spring-boot-configuration-processor`包,代码片段如下 ```xml org.springframework.boot spring-boot-configuration-processor true ``` 2) 编写`CustomProperties.class`,并使用`@ConfigurationProperties` ```java package com.lirisheng.experiment.autoConfig; import org.springframework.boot.context.properties.ConfigurationProperties; @ConfigurationProperties(prefix = "lirisheng.auto") public class CustomProperties { private boolean enable; public boolean isEnable(){return enable;} public void setEnable(boolean enable){this.enable=enable;} } ``` 3) 在`AutoConfig.class`中引入上面的类 ```java package com.lirisheng.experiment.autoConfig; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; //在这里引入该类 @EnableConfigurationProperties(CustomProperties.class) public class AutoConfig { @Bean @ConditionalOnProperty(prefix = "lirisheng.auto",name = "enable",havingValue = "true") HelloConfig helloConfig(){ return new HelloConfig(); } } ``` 4) 运行项目,在target下就会出现元数据文件
5) 然后在`applicaiton.properties`文件中就会出现相关提示
2) **自定义一个事件发布器** 1) 什么是Springboot的事件发布器 事件发布器发布事件,监听器来捕获事件的发布(如何捕获,就通过发布事件的类型进行匹配),从而对可以对事件做出一下相关操作,或者其他的一些操作 2) 如何自定义事件发布器 * 简述:需要我们自定义自定义事件发布器,为了对自定义的事件发布器进行演示,还有自定义一个事件,以及该该事件的相应的监听器 * 自定义事件发布器的步骤 1) 自定义事件发布器 ```java @Configuration public class EventConfiguration { @Bean(AbstractApplicationContext.APPLICATION_EVENT_MULTICASTER_BEAN_NAME) //把Springboot默认配置的线程池依赖注入 ApplicationEventMulticaster applicationEventMulticaster(ThreadPoolTaskExecutor taskExecutor) { SimpleApplicationEventMulticaster eventMulticaster =new SimpleApplicationEventMulticaster(); //事件发布器设置该线程池,从而使得其异步发布事件 eventMulticaster.setTaskExecutor(taskExecutor); return eventMulticaster; } } ``` 2) 自定义事件 ```java public class NoticeEvent extends ApplicationEvent { private static final Logger logger = LoggerFactory.getLogger(NoticeEvent.class); private final String message; public NoticeEvent(String message){ super(message); this.message=message; logger.info("添加事件成功!message:{}",message); } public String getMessage(){ return message; } } ``` 3) 自定义监听器 ```java @Component public class NoticeListener implements ApplicationListener { private static final Logger logger = LoggerFactory.getLogger(NoticeListener.class); @Override public void onApplicationEvent(NoticeEvent noticeEvent) { logger.info("事件监听器获取到 NoticeEvent,睡眠当前线程 2 秒...."); try{ Thread.sleep(2000); }catch (InterruptedException e){ e.printStackTrace(); } logger.info("NoticeEvent 的 message 属性是:{}",noticeEvent.getMessage()); } } ``` 4) 编写一个测试用例,进行测试 ```java @Test void testAsynMulticaster()throws InterruptedException{ eventMulticaster.multicastEvent(new NoticeEvent("东莞理工学院")); eventMulticaster.multicastEvent(new NoticeEvent("网络计算机与安全学院")); Thread.sleep(2000); } ``` 5) 测试结果
3) **扩展,如何自定义线程池,并把该线程池作为依赖注入到事件发布器中** 1) 总体思路 自定义一个线程池,然后把该线程池作为自动配置类加入到Springboot中 2) 如何自定义一个线程池,并作为自动配置类 ```java @EnableConfigurationProperties({CustomHelloProperties.class,CustomPoolTaskProperties.class}) public class AutoConfig { @Bean @ConditionalOnProperty(prefix = "lirisheng.auto",name = "enable",havingValue = "true") HelloConfig helloConfig(){ return new HelloConfig(); } @Bean("customPoolTask") ThreadPoolTaskExecutor threadPoolTaskExecutor(CustomPoolTaskProperties customPoolTaskProperties){ ThreadPoolTaskExecutor threadPoolTaskExecutor=new ThreadPoolTaskExecutor(); threadPoolTaskExecutor.setCorePoolSize(customPoolTaskProperties.getCorePoolSize()); threadPoolTaskExecutor.setMaxPoolSize(customPoolTaskProperties.getMaxPoolSize()); System.out.println("自动配置的自定义线程池customPoolTask其作用"); return threadPoolTaskExecutor; } } ``` 3) 配置该线程池的元数据,并利用该元数据来定制该线程池的corePoolSize,maxPoolSize属性 ```java @ConfigurationProperties(prefix = "lirisheng.taskpool") public class CustomPoolTaskProperties { private int corePoolSize=20; private int maxPoolSize=20; public int getCorePoolSize() { return corePoolSize; } public void setCorePoolSize(int corePoolSize) { this.corePoolSize = corePoolSize; } public int getMaxPoolSize() { return maxPoolSize; } public void setMaxPoolSize(int maxPoolSize) { this.maxPoolSize = maxPoolSize; } } ``` 4) 使用自定义线程池,即其依赖注入到上面的自定义的发布器中 ```java @Configuration public class EventConfiguration { @Bean(AbstractApplicationContext.APPLICATION_EVENT_MULTICASTER_BEAN_NAME) ApplicationEventMulticaster applicationEventMulticaster(@Qualifier("customPoolTask") ThreadPoolTaskExecutor taskExecutor){ SimpleApplicationEventMulticaster eventMulticaster =new SimpleApplicationEventMulticaster(); eventMulticaster.setTaskExecutor(taskExecutor); return eventMulticaster; } } ``` 5) 编写一个测试类,测试自定义的线程池 ```java @SpringBootTest class ExperimentApplicationTests { @Autowired ApplicationEventMulticaster eventMulticaster; @Test void contextLoads() { } @Test void testAsynMulticaster()throws InterruptedException{ eventMulticaster.multicastEvent(new NoticeEvent("东莞理工学院")); eventMulticaster.multicastEvent(new NoticeEvent("网络计算机与安全学院")); Thread.sleep(2000); } } ``` 6) 测试结果
### 五.实验总结 1) 知道Springboot提供的自动配置的原理实质上就是把自定义的类在Spring容器初始化的时候作为bean注入到容器中,但为了对这些自定义的配置类的集中管理,所以就有了`spring.factories`文件的发明 2) 事件发布器发布事件,监听器来捕获事件的发布(如何捕获,即可通过发布事件的类型进行匹配),从而对可以对事件做出一下相关操作,或者其他的一些操作