前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SpringBoot开篇

SpringBoot开篇

作者头像
用户1215919
发布2021-12-28 12:36:07
1610
发布2021-12-28 12:36:07
举报
文章被收录于专栏:大大的微笑大大的微笑

SpringBoot

前言:

SpringBoot是一个服务于Spring框架的框架,用来简化对于bean的获取, 快速构建一个web服务, 它的基础依然是Spring。

在SpringBoot还未出来以前使用的最多的架构体系可能是SpringMVC + Mybatis or Spring + Struts2 +Hibernate ,甚至是最早期的JSP + Servlet. 以上框架搭建起来过于繁琐,而且需要进行大量的配置,每次搭建一个web项目可能会遇到各种各样的问题,所以一般公司都会生成相应的脚手架,以便于能够提升开发效率。

随着互联网的发展,最开始的单体架构可能难以支撑大流量的场景, 那么架构演进的一个必然的结果是需要对于系统架构拆分,由最开始的单体架构拆分成N个业务系统,那么服务与服务之间的调用就需要提供相应的通信方式与协议等,例如HTTP 或者RPC(dubbo的底层通信方式是通过Netty实现,即暴露服务的端口供远程调用)的方式进行调用。

1.什么是SpringBoot

1.1. Spring基础,IOC 控制反转

包含以下两部分:

  • DI 依赖注入
  • DL 依赖查找

1.2. SpringBoot实现快速开发的基础来源于 约定优于配置

什么是约定优于配置:例如A和B两个人刚认识,为了升华一下双方的友谊,于是约定某天某一时刻在某地喝茶, 那么第二次可能只需要说老地方见就知道该去哪里,那么到了后来可能只需要一个眼神交流即可。

1.2.1 约定优于配置的体现

  • maven的目录结构(默认以jar的形式打包,默认会有resources目录)
  • springboot-starter-xxx的方式, e.g. springboot-starter(内置了tomcat, resource/{template,static} )

1.2.2. 为什么说SpringBoot里没有新技术

1.2.2.1. 自动装配

@SpringBootApplication 是由以下三个注解组成的

  • @SpringBootConfiguration

@Configuration 注解标注。 --> 本质上还是由@Component标注。 Spring最开始采用XML的方式 e.g. : <bean id="xxx" class ="com.xxxx.A"/>

Spring3开始支持 javaConfig的方式(始于JDK5), Spring3以后开始支持xmljavaConfig的方式

  • @EnableAutoConfiguration

Spring3.1后引入Enable* , e.g. : EnableScheduling, EnableCache EnableAsync ..

代码语言:javascript
复制
// 引入@Import({Registrar.class})
@AutoConfigurationPackage
// 相当于xml: `<import resource ="***"/>`, `AutoConfigurationImportSelector`最终继承于ImportSelector 
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
	// ....
}
实现动态注入的方式:

ImportSelectorImportBeanDefinitionRegistrar

代码语言:javascript
复制
// 方式①
public class CachedRegister implements ImportBeanDefinitionRegistrar {
  @Override
  public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
      RootBeanDefinition beanDefinition = new RootBeanDefinition(DiskPersistent.class);
      String beanName = StringUtils.uncapitalize(DiskPersistent.class.getName());
      // beanName相當於<bean name ="beanName"></bean>
      beanDefinitionRegistry.registerBeanDefinition(beanName, beanDefinition);
  }
// 方式②	
public class ProviderSelector implements ImportSelector {
  @Override
  public String[] selectImports(AnnotationMetadata annotationMetadata) {
      return new String[]{CachedService.class.getName(),HealthManagerService.class.getName()};
  }
}
// 控制台打印,可以获取到如下内容,这只是个简单的演示,可以在这里做一些其他的事情(加深自己的印象)
//HealthManagerService@57a4d5ee
//DiskPersistent@5af5def9	

AutoConfiguration (自动注入, 简化Bean的注入)

@EnableAutoConfiguration中导入了AutoConfigurationImportSelector 通过ImportSelector不难知道其中必定会有selectImports方法,

代码语言:javascript
复制
public String[] selectImports(AnnotationMetadata annotationMetadata) {
     if (!this.isEnabled(annotationMetadata)) {
         return NO_IMPORTS;
     } else {
			// 这里在加载META-INF/spring-autoconfigure-metadata.properties文件 
         AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
			//看这里
         AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata);
         return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
     }
 }

protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) {
     if (!this.isEnabled(annotationMetadata)) {
         return EMPTY_ENTRY;
     } else {
         AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
			// 看这里
         List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
			// 去重
         configurations = this.removeDuplicates(configurations);
			//过滤注解属性exlude={}
         Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
         this.checkExcludedClasses(configurations, exclusions);
         configurations.removeAll(exclusions);
         configurations = this.filter(configurations, autoConfigurationMetadata);
         this.fireAutoConfigurationImportEvents(configurations, exclusions);
         return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
     }
 }

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
	    // `SpringFactoriesLoader` (`spring SPI机制`),这里会加载所有的 `META-INF/spring.factories`文件里的数据
     List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
     Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
     return configurations;
 }

spi(service provider interface) 是什么? --> 提供扩展点供开发人员使用 e.g. java ,spring,dubbo都提供了相应的spi

在META-INF下创建: spring.factories 添加自己的类即可加载: e.g.: org.springframework.boot.autoconfigure.EnableAutoConfiguration= xxx.xxx.A

如下是spring自带的的:

代码语言:javascript
复制
  # `AutoConfiguration`
  `org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  org.springframework.cloud.client.CommonsClientAutoConfiguration,\
  org.springframework.cloud.client.discovery.composite.CompositeDiscoveryClientAutoConfiguration,\`
  // 略...

条件注册:**

NOTE:

因为SpringBoot会考虑到各种各样的场景,所以需要加载的资源会比较多,而有些时候大部分场景我们压根使用不到,所以可以通过条件注解

使用方式:

ConditionalOnXXX e.g. ConditionalOnClass = "com.xxx.A"META-INF下添加 spring-autoconfigure-metadata.properties

代码语言:javascript
复制
  com.a.AConfig.ConditionalOnClass  = com.xxx.A
  
  // spring中的
  org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration.ConditionalOnClass=org.influxdb.InfluxDB
  @AutoConfigurationPackage
  @Import({AutoConfigurationImportSelector.class})
  • @ComponentScan

扫描 @Component, @Service, @Controller, @Configuration 等(注解具有派生性,@Component及派生注解都将被扫描) 然后被IOC托管。 等价于 : Spring XML的方式<context-componet-scan />

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言:
  • 实现动态注入的方式:
    • NOTE:
      • 使用方式:
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档