SpringBoot开篇

SpringBootjava

前言:

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

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

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

1.什么是SpringBoottomcat

1.1. Spring基础,IOC 控制反转springboot

包含如下两部分:架构

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

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

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

1.2.1 约定优于配置的体现ide

  • 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 ..

// 引入@Import({Registrar.class})
@AutoConfigurationPackage
// 至关于xml: `<import resource ="***"/>`, `AutoConfigurationImportSelector`最终继承于ImportSelector 
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
	// ....
}

实现动态注入的方式:

ImportSelectorImportBeanDefinitionRegistrar

// 方式①
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方法,

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自带的的:

# `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

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 />

相关文章
相关标签/搜索