lilele200706

 

SpringBoot学习之始

SpringBoot

  1. 什么是SpringBoot?

  2. 它的运行原理是什么?

  3. 它的配置文件如何编写。

  4. 如何使用它开发web项目。

  5. 它是如何集成数据库的,druid

  6. 权限管理如何做

  7. swagger:接口文档

  8. 任务调度

  9. 分布式开发:Dubbo+Zookeeper

一、SpringBoot是什么

它就是一个javaweb的开发框架,和SpringMVC类似。SpringBoot是基于Spring开发,SpringBoot本身并不提供Spring框架的核心特性以及扩展功能,只是用于快速、敏捷的开发新一代基于Spring的应用程序。它并不是用来代替spring 的,而是与Spring结合起来提升Spring开发者体验的工具。SpringBoot以约定大于配置的思想,帮我们提供了很多默认配置,我们只需要很少的Spring配置,就可以开发出来一个应用程序。它默认配置了很多框架的使用方式,集成第三方框架,几乎可以零配置的开箱即用。maven整合了所有的jar包,SpringBoot整合了所有的框架。

二、SpringBoot能干什么

对比其他javaweb框架的好处,官方说是简化开发,约定大于配置,you can "just run",能迅速的开发web应用,几行代码开发一个http接口。

  • 为所有Spring开发者更快的入门

  • 开箱即用,提供各种默认配置来简化项目配置

  • 内嵌式容器简化web项目

  • 没有冗余代码生成和xml配置的要求

三、SpringBoot怎么使用

1. 第一个SpringBoot程序

  1. 使用Spring Initializr创建一个SpringBoot程序

    • G com.lele

    • A hellofirst

    • 默认的包中将hellofirst删掉,比较方便

  2. 选择web,添加spring web依赖,完成

  3. 默认创建了包com.lele.hellofirst,并在hellofirst包下创建了HellofirstApplication.class启动类。

  4. 在hellofirst包下新建一个包controller,与启动类同级,Springboot会扫描与启动类同级的包,而不会扫描同级的类

  5. 在controller包下新建一个类HelloController

@RestController
public class HelloController {
   @RequestMapping("/hello")
   public String get(){
       return "Hello,SpringBoot!"
  }
}
  1. 第一个SpringBoot程序写好了,可以通过启动类启动程序。通过http://localhost:8080/hello访问。

2.更改Tomcat的端口号

server:
port:8081

3.更改banner

在resource下新建一个banner.txt,将自定义的图片,艺术字等放进去。

四、原理初探

自动配置:核心是pom

  1. pom中有parent<artifactId>spring-boot-starter-parent</artifactId>,进去后还有parent<artifactId>spring-boot-dependencies</artifactId>,点击去后无parent了,有各种jar包

    <properties>
       <activemq.version>5.16.3</activemq.version>
       <antlr2.version>2.7.7</antlr2.version>
       <appengine-sdk.version>1.9.92</appengine-sdk.version>
      ...
       <wsdl4j.version>1.6.3</wsdl4j.version>
       <xml-maven-plugin.version>1.0.2</xml-maven-plugin.version>
       <xmlunit2.version>2.8.3</xmlunit2.version>
     </properties>

    而在<artifactId>spring-boot-starter-parent</artifactId>中,有资源过滤自动配好了,插件也配置好了。

     <build>
       <resources>
         <resource>
           <directory>${basedir}/src/main/resources</directory>
           <filtering>true</filtering>
           <includes>
             <include>**/application*.yml</include>
             <include>**/application*.yaml</include>
             <include>**/application*.properties</include>
           </includes>
         </resource>
         <resource>
           <directory>${basedir}/src/main/resources</directory>
           <excludes>
             <exclude>**/application*.yml</exclude>
             <exclude>**/application*.yaml</exclude>
             <exclude>**/application*.properties</exclude>
           </excludes>
         </resource>
       </resources>
       <pluginManagement>
         <plugins>
           <plugin>
             <groupId>org.jetbrains.kotlin</groupId>
             <artifactId>kotlin-maven-plugin</artifactId>
             <version>${kotlin.version}</version>
             <configuration>
               <jvmTarget>${java.version}</jvmTarget>
               <javaParameters>true</javaParameters>
             </configuration>
             <executions>
               <execution>
                 <id>compile</id>
                 <phase>compile</phase>
                 <goals>
                   <goal>compile</goal>
                 </goals>
               </execution>
               <execution>
                 <id>test-compile</id>
                 <phase>test-compile</phase>
                 <goals>
                   <goal>test-compile</goal>
                 </goals>
               </execution>
             </executions>
           </plugin>
         </plugins>
       </pluginManagement>
     </build>

    而在本身的pom中,有启动器。

    <dependencies>
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
      </dependency>

      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-test</artifactId>
          <scope>test</scope>
      </dependency>
    </dependencies>
  • 启动器:SpringBoot的启动场景。

  • eg:spring-boot-starter-web,它就会帮我们自动导入web环境所有的依赖!

  • springboot 会将所有的功能场景,都变成一个个的启动器。

  • 我们需要什么功能,导入所需的启动器就可以了。starter

五、主程序

@SpringBootApplication  //标注这个类是一个SpringBoot的应用,启动类下的所有资源被导入
public class HellofirstApplication {
   public static void main(String[] args) {
       //这是一个将SpringBoot应用启动的方法
       //该方法返回一个ConfigurableApplicationContext对象
       //参数一:应用入口的类       参数类:命令行参数
       SpringApplication.run(HellofirstApplication.class, args);
  }
}

1.@SpringBootApplication点击进入后

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration   //SpringBoot的配置,点击进去
@EnableAutoConfiguration //自动配置,点击进去
//扫描包下的文件,剔除不要的
@ComponentScan(excludeFilters = {@Filter(type = FilterType.CUSTOM,classes{TypeExcludeFilter.class}), @Filter(type = FilterType.CUSTOM,classes = {AutoConfigurationExcludeFilter.class})})
public @interface SpringBootApplication {
  • @SpringBootConfiguration //SpringBoot的配置,点击进去

  • @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Configuration //Spring配置类,说明启动类也是一个配置类。点击进去
    @Indexed
    public @interface SpringBootConfiguration {
    • @Configuration //Spring配置类,说明启动类也是一个配置类。点击进去

    • @Target({ElementType.TYPE})
      @Retention(RetentionPolicy.RUNTIME)
      @Documented
      @Component //这也是一个spring的组件
      public @interface Configuration {
  • @EnableAutoConfiguration //自动配置,点击进去

  • @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @AutoConfigurationPackage //自动配置包,点击进去
    @Import({AutoConfigurationImportSelector.class})//自动配置导入选择器,点击进去
    public @interface EnableAutoConfiguration {
    • @AutoConfigurationPackage //自动配置包,点击进去

    • @Target({ElementType.TYPE})
      @Retention(RetentionPolicy.RUNTIME)
      @Documented
      @Inherited
      @Import({Registrar.class}) //自动配置.包注册,点击进去
      public @interface AutoConfigurationPackage {
      • @Import({Registrar.class}) //自动配置.包注册,点击进去

      • static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports { Registrar() { }
    • @Import({AutoConfigurationImportSelector.class})//自动配置导入选择器,点击进去

    • public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
        ...
          //选择组件,选择pom中导入的依赖,如果没有,就无法判断导入哪些依赖
          public String[] selectImports(AnnotationMetadata annotationMetadata) {
             if (!this.isEnabled(annotationMetadata)) {
                 return NO_IMPORTS;
            } else {
                 AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);
                 return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
            }
        }
         //获取候选的配置
         protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(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);
                 Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
                 this.checkExcludedClasses(configurations, exclusions);
                 configurations.removeAll(exclusions);
                 configurations = this.getConfigurationClassFilter().filter(configurations);
                 this.fireAutoConfigurationImportEvents(configurations, exclusions);
                 return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
            }
        }
      • // 获取候选的配置 点击进去 List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);

        • protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
             //加载
                 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;
            }
          • protected ClassLoader getBeanClassLoader() {
                return this.beanClassLoader; //点击进去
            }
            • private ClassLoader beanClassLoader;//加载器,用来本类的
          • protected Class<?> getSpringFactoriesLoaderFactoryClass() {
                   return EnableAutoConfiguration.class;//
              }
          • META-INF/spring.factories//自动配置的核心文件

          • image-20211211134109704

          • 核心文件里有各种自动配置的类,eg:WebMvcAutoConfiguration

          • @Configuration(
               proxyBeanMethods = false
            )
            @ConditionalOnWebApplication(
               type = Type.SERVLET
            )
            @ConditionalOnClass({Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class})
            //判断者这个类是否生效
            @ConditionalOnMissingBean({WebMvcConfigurationSupport.class})
            @AutoConfigureOrder(-2147483638)
            @AutoConfigureAfter({DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class})
            public class WebMvcAutoConfiguration {
              ...
               @EnableConfigurationProperties({WebProperties.class})
               public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration implements ResourceLoaderAware {
                   private final Resources resourceProperties;
                   private final WebMvcProperties mvcProperties; //mvc配置
                   private final WebProperties webProperties;
                   private final ListableBeanFactory beanFactory;
                   private final WebMvcRegistrations mvcRegistrations;
                   private ResourceLoader resourceLoader;
              ...
                //视图解析器
                private ResourceResolver getVersionResourceResolver(Strategy properties) {
                       VersionResourceResolver resolver = new VersionResourceResolver();
                       if (properties.getFixed().isEnabled()) {
                           String version = properties.getFixed().getVersion();
                           String[] paths = properties.getFixed().getPaths();
                           resolver.addFixedVersionStrategy(version, paths);
                      }

                       if (properties.getContent().isEnabled()) {
                           String[] paths = properties.getContent().getPaths();
                           resolver.addContentVersionStrategy(paths);
                      }

                       return resolver;
                  }
              ...
            }
          • private final WebMvcProperties mvcProperties; //mvc配置,点击进去

            • public class WebMvcProperties {
                 private org.springframework.validation.DefaultMessageCodesResolver.Format messageCodesResolverFormat;
                 private final WebMvcProperties.Format format = new WebMvcProperties.Format();
                ...
                 private final WebMvcProperties.Servlet servlet = new WebMvcProperties.Servlet();
                 private final WebMvcProperties.View view = new WebMvcProperties.View();
                 private final WebMvcProperties.Contentnegotiation contentnegotiation = new WebMvcProperties.Contentnegotiation();
                 private final WebMvcProperties.Pathmatch pathmatch = new WebMvcProperties.Pathmatch();
      • SpringFactoriesLoader

        • //标注了SpringApplication这个类
          public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
                 ClassLoader classLoaderToUse = classLoader;
                 if (classLoader == null) {
                     classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
                }

                 String factoryTypeName = factoryType.getName();
                 return (List)loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());//
            }
          private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
                 Map<String, List<String>> result = (Map)cache.get(classLoader);
                 if (result != null) {
                     return result;
                } else {
                     HashMap result = new HashMap();

                     try {
                         Enumeration urls = classLoader.getResources("META-INF/spring.factories");//从spring.factories中获取资源

                         while(urls.hasMoreElements()) {//有没有更多的元素
                             URL url = (URL)urls.nextElement();
                             UrlResource resource = new UrlResource(url);
                             Properties properties = PropertiesLoaderUtils.loadProperties(resource);//所有的资源加载到配置类中
                             Iterator var6 = properties.entrySet().iterator();

                             while(var6.hasNext()) {
                                 Entry<?, ?> entry = (Entry)var6.next();
                                 String factoryTypeName = ((String)entry.getKey()).trim();
                                 String[] factoryImplementationNames = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
                                 String[] var10 = factoryImplementationNames;
                                 int var11 = factoryImplementationNames.length;

                                 for(int var12 = 0; var12 < var11; ++var12) {
                                     String factoryImplementationName = var10[var12];
                                    ((List)result.computeIfAbsent(factoryTypeName, (key) -> {
                                         return new ArrayList();
                                    })).add(factoryImplementationName.trim());
                                }
                            }
                        }

                         result.replaceAll((factoryType, implementations) -> {
                             return (List)implementations.stream().distinct().collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
                        });
                         cache.put(classLoader, result);
                         return result;
                    } catch (IOException var14) {
                         throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var14);
                    }
                }
            }

结论:SpringBoot所有的自动配置都在启动类中扫描并被加载。spring.factories所有的自动配置类都在这里面,但是不一定生效,要判断条件是否成立,只有导入了starter的,有了对应的启动器,自动配置才会生效,然后有配置成功。

  1. SpringBoot在启动的时候,从类路径下/META-INF/spring.factories获得指定的值。

  2. 将浙西自动配置的类导入容器,自动配置就会生效,帮我们进行自动配置。

  3. 以前需要我们自己配置的东西,现在SpringBoot帮我们做了。

  4. 整合javaEE,解决方案和自动配置的东西都在spring-boot-autoconfiguration 2.20 RELEASE.jar这个包下

  5. 它会把所有需要导入的组件,以类名的方式返回,这些组件就会被添加到容器。

  6. 容器中也会存在非常多的xxxAutoConfiguration的文件(@Bean),就是这些给容器中导入了这个场景需要的所有组件,并自动配置,@Configuration,JavaConfig

  7. 有了自动配置类,就免去了我们手动配置文件的工作。

2. SpringApplication.run(***.class,args);

我们以为运行了一个main方法,没想到却开启了一个服务。分析该方法主要分为两个部分,一部分是SpringApplication的实例化,一部分是run方法的执行。

SpringApplication

这个类主要做了以下四件事情:

  1. 推断应用的类型是普通的项目还是web项目。

  2. 查找并加载所有可用的初始化器,设置到initializers属性中

  3. 找出所有的应用程序监听器,设置到listeners属性中

  4. 推断并设置main方法的定义类,找到运行的主类。

核心就是JavaConfig @Configuration @Bean

Docker:进程。

posted on 2021-12-12 18:13  lilele200706  阅读(60)  评论(0)    收藏  举报

导航