# springboot-study **Repository Path**: wlyfree/springboot-study ## Basic Information - **Project Name**: springboot-study - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2019-09-03 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # `SpringBoot Application` > `SpringBootApplication`类是`SpringBoot`驱动`spring`上下文的引导类 ##### 启动`SpringBoot`项目的三种方式 ```java // 启动方式一(默认) SpringApplication.run(SpringbootStudyApplication.class, args); // 启动方式二(builder模式),方法后边一直“.”的api叫:fluent API(流畅的API) new SpringApplicationBuilder(SpringbootStudyApplication.class).properties("server.port=0").run(args); // 启动方式三: SpringApplication springApplication = new SpringApplication(SpringbootStudyApplication.class); // 设置项目为非Web项目 // springApplication.setWebApplicationType(WebApplicationType.NONE); Map properties = new LinkedHashMap<>(); // 随机端口号 properties.put("server.port", 0); springApplication.setDefaultProperties(properties); ConfigurableApplicationContext configurableApplicationContext = springApplication.run(args); System.out.println(configurableApplicationContext.getClass().getName()); ``` ##### `spring`应用类型推断 ``` // 创建spring应用 new SpringApplication(); // 类型推断 this.webApplicationType = WebApplicationType.deduceFromClasspath(); ``` ##### `@SpringBootApplication`注解 `@SpringBootApplication`注解等同于以下注解 `@SpringBootConfiguration`等同于`@Configuration` `@EnableAutoConfiguration`:激活自动装配,`@Enable..`开头的注解是`Enable`模式,有两种编程模型 `@ComponentScan`:Spring Framework 3.1引入的,用于模块扫描 ```java // @SpringBootApplication源码: @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan( excludeFilters = {@Filter( type = FilterType.CUSTOM, classes = {TypeExcludeFilter.class} ), @Filter( type = FilterType.CUSTOM, classes = {AutoConfigurationExcludeFilter.class} )} ``` ##### `@Component`注解的派生性 `@Controller`、`@Service`、`@Repository`、`@Configuration` ```java @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Controller { ... } ``` ##### spring扩展点 `BeanDefinitionRegistryPostProcessor`接口:Bean注册扩展点,可以动态地注册Bean `BeanPostProcessor`接口:Bean初始化扩展点,每个Bean初始化后都会调用一次 `BeanFactoryPostProcessor`接口:Spring容器扩展点,spring容器初始化之后触发,只会触发一次,可以驱动标记为`@Configuration`的注解类 ##### spring bean的解析过程 ```java // Bean注册扩展点接口继承Spring容器扩展点接口 public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor // ConfigurationClassPostProcessor类可以解析标注为@Configuration的类 public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor... { public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) { // Parse each @Configuration class ConfigurationClassParser parser = new ConfigurationClassParser(...) } } class ConfigurationClassParser { // @ComponentScan解析类 private final ComponentScanAnnotationParser componentScanParser; // 解析配置入口 protected void processConfigurationClass(ConfigurationClass configClass) throws IOException { doProcessConfigurationClass(configClass, sourceClass); } // 核心解析方法,处理@ComponentScan、@Import等注解 protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass) throws IOException { // Recursively process any member (nested) classes first // Process any @PropertySource annotations // Process any @ComponentScan annotations // 处理@ComponentScan注解 this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName()); // Process any @Import annotations // Process any @ImportResource annotations // Process individual @Bean methods // Process default methods on interfaces // Process superclass, if any } } ``` - `BeanDefinitionRegistryPostProcessor implements BeanFactoryPostProcessor`,`BeanFactoryPostProcessor`驱动`@Configuration`的注解类 - 使用`ConfigurationClassParser`解析,->`ComponentScanAnnotationParser.parse()`->`new ClassPathBeanDefinitionScanner()` -> `ClassPathBeanDefinitionScanner.registerDefaultFilters()` - `registerDefaultFilters()`中对`@Component`以及`@Controller`、`@Service`、`@Repository`做解析 ##### `spring`驱动 `BeanDefinition`:Bean定义,可以简单理解为这两个注解:`@Configuration`、`@Bean` `ClassPathXmlApplicationContext`:xml配置文件驱动 `AnnotationConfigApplicationContext`:注解驱动 ##### `spring事件` `ApplicationEvent`:spring事件类型,相当于消息内容 `ApplicationListener`:spring事件监听,相当于消息消费者、订阅者 `ApplicationEventMulticaster`:spring事件广播,相当于消息生产者、发布者 ```java public class SpringEventTest { public static void main(String[] args) { ApplicationEventMulticaster multicaster = new SimpleApplicationEventMulticaster(); // 监听事件 multicaster.addApplicationListener(event -> { System.out.println("收到事件,事件类:" + event.getClass().getSimpleName() + ",事件内容:" + event.getSource()); }); // 广播事件 multicaster.multicastEvent(new PayloadApplicationEvent("1", "hello")); multicaster.multicastEvent(new PayloadApplicationEvent("2", "hi")); } } ``` ##### `springboot`事件 ```java public static void main(String[] args) { new SpringApplicationBuilder(SpringbootStudyApplication.class) // listeners监听事件 .listeners(event -> { System.out.println("监听到的事件" + event.getClass().getSimpleName()); }) // 随机端口号 .properties("server.port=0") .run(args); } ``` ```java // 控制台 监听到的事件ApplicationStartingEvent 监听到的事件ApplicationEnvironmentPreparedEvent . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.1.7.RELEASE) 监听到的事件ApplicationContextInitializedEvent 2019-09-01 13:22:52.064 INFO 9764 --- [ main] com.wang.SpringbootStudyApplication : Starting SpringbootStudyApplication on wlyfree-PC with PID 9764 (F:\study\springboot-study\target\classes started by wlyfree in F:\study\springboot-study) 2019-09-01 13:22:52.074 INFO 9764 --- [ main] com.wang.SpringbootStudyApplication : No active profile set, falling back to default profiles: default 监听到的事件ApplicationPreparedEvent 2019-09-01 13:22:53.273 INFO 9764 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 0 (http) 2019-09-01 13:22:53.293 INFO 9764 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2019-09-01 13:22:53.293 INFO 9764 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.22] 2019-09-01 13:22:53.406 INFO 9764 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2019-09-01 13:22:53.406 INFO 9764 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1302 ms 2019-09-01 13:22:53.579 INFO 9764 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor' 监听到的事件ContextRefreshedEvent 2019-09-01 13:22:53.729 INFO 9764 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 54401 (http) with context path '' 监听到的事件ServletWebServerInitializedEvent 2019-09-01 13:22:53.729 INFO 9764 --- [ main] com.wang.SpringbootStudyApplication : Started SpringbootStudyApplication in 2.21 seconds (JVM running for 3.052) 监听到的事件ApplicationStartedEvent 监听到的事件ApplicationReadyEvent ``` 事件监听配置文件:spring-boot-2.0.3-RELEASE.jar/META-INF/spring.factories ```shell # Application Listeners org.springframework.context.ApplicationListener=\ org.springframework.boot.ClearCachesApplicationListener,\ org.springframework.boot.builder.ParentContextCloserApplicationListener,\ org.springframework.boot.context.FileEncodingApplicationListener,\ org.springframework.boot.context.config.AnsiOutputApplicationListener,\ org.springframework.boot.context.config.ConfigFileApplicationListener,\ org.springframework.boot.context.config.DelegatingApplicationListener,\ org.springframework.boot.context.logging.ClasspathLoggingApplicationListener,\ org.springframework.boot.context.logging.LoggingApplicationListener,\ org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener ``` ##### spring流程 扫描并注册Bean:`@Configuration`->`@ComponentScan.basepackages`->`@Component Beans`->`BeanDefintion`->`BeanDefinitionRegistry`->`Beans` 使用Bean:`BeanFactory.getBean or @Autowired` ##### spring生命周期 实例化:`Bean Class`->`Bean Object` 初始化:`Bean init()`-> ​ 初始化前:`BeanPostProcessor#postProcessBeforeInitialization()` ​ 初始化:`InitializingBean#afterPropertiesSet()` ​ 初始化后:`BeanPostProcessor#postProcessAfterInitialization` 销毁:`Bean destory()`->`DisposableBean.dispost()` ##### `spring MVC` 入口:`DispatcherServlet` M:模型->`Model、ModelMap、ModelAndView(Model部分)、@ModelAttribute` V:视图->`view` C:控制器->`DispatcherServlet` ##### `spring MVC`流程 ![](C:\Users\wlyfree\Desktop\springMVC.png) ##### `spring`注解和元注解 ```java # GetMapping、PostMapping...的元注解是@RequestMapping,@AliasFor标注的是元注解的属性,如下PostMapping.value实际是RequestMapping中的 @RequestMapping( method = {RequestMethod.POST} ) public @interface PostMapping { @AliasFor( annotation = RequestMapping.class ) String[] value() default {}; } ``` ##### `@EnableWebMvc`注解 ###### `EnableWebMvc`引入`DelegatingWebMvcConfiguration`注解 ```java @Import({DelegatingWebMvcConfiguration.class}) public @interface EnableWebMvc { .. } ``` ###### `DelegatingWebMvcConfiguration`注册`WebMvcConfigurer` ```java @Autowired(required = false) public void setConfigurers(List configurers) { if (!CollectionUtils.isEmpty(configurers)) { this.configurers.addWebMvcConfigurers(configurers); } } ``` ###### `WebMvcConfigurer` - 装配各种`spring MVC`需要的Bean - 注解驱动扩展点 ```java public interface WebMvcConfigurer { ... // 解析入参 default void addArgumentResolvers(List resolvers) { } // 解析出参 default void addReturnValueHandlers(List handlers) { } ... } ``` ###### `RequestResponseBodyMethodProcessor`类 - 实现`HandlerMethodArgumentResolver`和`HandlerMethodReturnValueHandler`接口 - `@RequestBody`和`@ResponseBody`的实现类 ![](F:\study\springboot-study\src\main\resources\images\RequestResponseBodyMethodProcessor类图.png) ###### `HttpMessageConverter`接口(Spring核心的Http消息转换器) `RequestResponseBodyMethodProcessor`底层使用`HttpMessageConverter`接口来处理入参和出参。 `HttpMessageConverter`接口的常用实现 - `MappingJackson2HttpMessageConverter`:处理json类型的参数 - `StringHttpMessageConverter`处理普通文本 ##### `RestTemplate` ###### 消息转换器 添加了内建的`HttpMessageConverter`的实现 有条件的添加了第三方的`HttpMessageConverter`的实现,如`Gson`,这里存在一个优先级的问题,比如`curl`、`postman`在请求的时候若没有指定协议,可能使用优先级更高的转化器,如`xml` ```java public RestTemplate() { this.messageConverters = new ArrayList(); ... this.messageConverters.add(new ByteArrayHttpMessageConverter()); this.messageConverters.add(new StringHttpMessageConverter()); ... if(jackson2XmlPresent) { this.messageConverters.add(new MappingJackson2XmlHttpMessageConverter()); } else if(jaxb2Present) { this.messageConverters.add(new Jaxb2RootElementHttpMessageConverter()); } } ``` ###### 拦截器 `RestTemplate` 继承`InterceptingHttpAccessor` ```java public class RestTemplate extends InterceptingHttpAccessor implements RestOperations { ... } public abstract class InterceptingHttpAccessor extends HttpAccessor { ... // 设置拦截器 public void setInterceptors(List interceptors) { if(this.interceptors != interceptors) { this.interceptors.clear(); this.interceptors.addAll(interceptors); AnnotationAwareOrderComparator.sort(this.interceptors); } } ... } ``` 可以在拦截器里实现负载均衡等操作 # `SpirngCloud` ## 服务发现 | 比较点 | Eureka | Zookeeper | Consul | | ------------- | ------------------------------------------------------- | ---------------------------- | ------------------------- | | 运维熟悉度 | 相对陌生 | 熟悉 | 更陌生 | | 一致性(CAP) | AP(最终一致性) | CP(一致性强) | AP(最终一致性) | | 一致性协议 | HTTP 定时轮训 | ZAB | RAFT | | 通讯方式 | HTTP REST | 自定义协议 | HTTP REST | | 更新机制 | Peer 2 Peer(服务器之间) + Scheduler(服务器和客户端) | ZK Watch | Agent 监听的方式 | | 适用规模 | 20 K ~ 30 K 实例(节点) | 10K ~ 20K 实例(节点) | < 3K 实例(节点) | | 性能问题 | 简单的更新机制、复杂设计、规模较大时 GC 频繁 | 扩容麻烦、规模较大时 GC 频繁 | 3K 节点以上,更新列表缓慢 | ##### `DiscoveryClient` ```shell # TODO ```