SpringBoot2学习笔记(一)

说明:参考b站雷神springboot2
视频参考
笔记参考

一、基础入门

1、SpringBoot优点
  • 创建独立Spring应用

  • 内嵌web服务器

    以前需要打包war包,放入tomcat才能运行

  • 自动starter依赖,简化构建配置

    starter启动器,自动依赖

  • 自动配置Spring以及第三方功能

  • 提供生产级别的监控、健康检查及外部化配置

  • 无代码生成、无需编写XML

SpringBoot是整合Spring技术栈的一站式框架

SpringBoot是简化Spring技术栈的快速开发脚手架

2、SpringBoot缺点
  • 人称版本帝,迭代快,需要时刻关注变化
  • 封装太深,内部原理复杂,不容易精通
3、时代背景

微服务、分布式、云原生

二、HelloWord

1、版本要求
Maven3.5+
Gradle6.8.x, 6.9.x, and 7.x
2、maven
配置阿里云仓库,下载速度更快
<mirrors>
      <mirror>
        <id>nexus-aliyun</id>
        <mirrorOf>central</mirrorOf>
        <name>Nexus aliyun</name>
        <url>http://maven.aliyun.com/nexus/content/groups/public</url>
      </mirror>
  </mirrors>
 
  <profiles>
         <profile>
              <id>jdk-1.8</id>
              <activation>
                <activeByDefault>true</activeByDefault>
                <jdk>1.8</jdk>
              </activation>
              <properties>
                <maven.compiler.source>1.8</maven.compiler.source>
                <maven.compiler.target>1.8</maven.compiler.target>
                <maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
              </properties>
         </profile>
  </profiles>
3、创建项目

注意idea中配置maven

pom.xml

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.4.RELEASE</version>
</parent>

<!-- 添加web依赖-->
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

主函数

package com.mys.boot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class MainApplication {
    public static void main(String[] args) {
        SpringApplication.run(MainApplication.class, args);
    }

}
//业务逻辑
package com.mys.boot.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

//@ResponseBody //每个方法返回的数据,直接返回给浏览器的数据,而不是跳转
//@Controller
@RestController //包含 @ResponseBody @Controller
public class HelloController {

    @RequestMapping("/hello")
    public String handle01() {
        return "hello";
    }
}

Spring Boot统一配置文件:application.properties

server.port=8888

简化部署:安装插件,把项目打成jar包,直接在目标服务器执行即可

<build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
</build>

三、自动配置原理

1、依赖管理
<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.4.RELEASE</version>
</parent>

他的父项目
 <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-dependencies</artifactId>
    <version>2.3.4.RELEASE</version>
  </parent>

几乎声明了所有开发中常用的依赖的版本号,自动版本仲裁机制

可以修改默认版本号

1、查看spring-boot-dependencies里面规定当前依赖的版本 用的 key。
2、在当前项目里面重写配置
    <properties>
        <mysql.version>5.1.43</mysql.version>
    </properties>
2、场景启动器
1、见到很多 spring-boot-starter-* : *就某种场景
2、只要引入starter,这个场景的所有常规需要的依赖我们都自动引入
3、SpringBoot所有支持的场景
https://docs.spring.io/spring-boot/docs/current/reference/html/using-spring-boot.html#using-boot-starter
4、见到的  *-spring-boot-starter: 第三方为我们提供的简化开发的场景启动器。
5、所有场景启动器最底层的依赖
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter</artifactId>
  <version>2.3.4.RELEASE</version>
  <scope>compile</scope>
</dependency>

1、引入依赖默认都可以不写版本
2、引入非版本仲裁的jar,要写版本号。
3、自动配置
  • 自动配好tomcat

1.引入tomcat依赖

2.配置tomcat

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-tomcat</artifactId>
  <version>2.3.4.RELEASE</version>
  <scope>compile</scope>
</dependency>
  • 自动配好SpringMVC

    1.引入SpringMVC全套组件

    2.自动配好SpringMVC常用组件

  • 自动配置好web常见功能,如字符编码

    springboot配置好了所有web开发的常见场景

  • 默认的包结构

    主程序所在的包,及其下面所有子包的组件都会默认扫描,无需配置以前的包扫描

    • 想要改变扫描路径,@SpringBootApplication(scanBasePackages=“com.atguigu”)

    • 或者**@ComponentScan** 指定扫描路径

      @SpringBootApplication
      等同于
      @SpringBootConfiguration
      @EnableAutoConfiguration
      @ComponentScan("com.mys.boot")
      
  • 各种配置有默认值

    • 默认配置最终都是映射到某个类上,如:MultipartProperties

      配置文件的值最终会绑定每个类上,这个类会在容器中创建对象

      想要改变默认的属性值,在application.properties中修改对应值

  • 按需加载所有自动配置项

    • 引入了哪些场景这个场景的自动配置才会开启
    • SpringBoot所有的自动配置功能都在 spring-boot-autoconfigure 包里面
4、容器
4.1组件添加

1、@Configuration

Full(proxyBeanMethods = true)      使用场景:组件依赖
Lite(proxyBeanMethods = false)
如果给容器中只是注册组件,别人也不依赖这个组件,选取false,这样可以 加速容器启动
package com.mys.boot.config;

import com.mys.boot.bean.Pet;
import com.mys.boot.bean.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 1.配置类里面使用@Bean标注在方法上给容器注册组件, 默认是单实例
 * 2.配置类本身也是组件
 * 3.proxyBeanMethods:代理bean的方法
 */

@Configuration(proxyBeanMethods = false)//告诉springboot这是一个配置类 == 配置文件
public class MyConfig {
    /**
     * 给容器中添加组件,以方法名作为组件id,返回类型是组件类型,返回的值是组件在容器中的实例
     * 外部无论对配置类中注册的组件调用多少次,获取的都是容器中之前注册的单实例对象
     * @return
     */
    @Bean
    public User user01() {
        User user = new User("zhangshan", 18);
        //user组件依赖了pet组件
        user.setPet(tomcatPet());
        return user;
    }

    @Bean("tom")//如果不想要方法名作为组件名,可以修改
    public Pet tomcatPet() {
        return new Pet("tomcat");
    }
}
package com.mys.boot;

import com.mys.boot.bean.Pet;
import com.mys.boot.bean.User;
import com.mys.boot.config.MyConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication
public class MainApplication {
    public static void main(String[] args) {

        //1.返回IOC容器
        ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);

        //2.查看容器里面的组件
        String[] names = run.getBeanDefinitionNames();
        for (String name : names) {
            System.out.println(name);
        }

        //3.容器中注册的组件是单实例的
        Pet tom01 = run.getBean("tom", Pet.class);
        Pet tom02 = run.getBean("tom", Pet.class);
        System.out.println("组件:" + (tom01 == tom02));

        //4.获取容器中配置类的组件
        MyConfig bean = run.getBean(MyConfig.class);
        System.out.println(bean);

        //5.配置类调用容器中声明的组件,判断是从容器拿的还是直接调用的方法
        //MyConfig代理对象调用方法 
        //proxyBeanMethods默认true ,表明从容器中拿的是注册的单实例对象
        //如果设置proxyBeanMethods=false,从容器中拿到的MyConfig就不是代理对象
        User user1 = bean.user01();
        User user2 = bean.user01();
        System.out.println(user1 == user2);

        //6.测试组件依赖关系
        User user01 = run.getBean("user01", User.class);
        Pet tom = run.getBean("tom", Pet.class);
        System.out.println("用户的宠物:" + (user01.getPet() == tom));
    }
}

@Bean @Component @Controller @Service @Repository @ComponentScan

2、@Import

导入指定类型组件,自动在容器中创建所导入的组件,默认组件的名字是全类名

@Import({User.class, DBHelper.class})

3、Conditional 条件装配

ConditionalOnBean、ConditionalOnMissingBean

4、@ImportResource(“classpath:beans.xml”)导入spring配置文件

4.2 配置绑定

1、@ConfigurationProperties+@Component

package com.mys.boot.bean;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component//只有在容器中的组件,才有拥有springboot提供的功能
@ConfigurationProperties(prefix = "mycar")
public class Car {
    private String brand;
    private Integer price;
		......
}
//application.properties中设置属性值
mycar.brand=BYD
mycar.price=10000

2、@EnableConfigurationProperties

@EnableConfigurationProperties(Car.class)
//1.开启car的配置绑定功能
//2.自动注册car组件到容器中
4.3 原理分析

1、引导加载自动配置类

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
      @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
  • @SpringBootConfiguration 代表是springboot

    @Configuration 代表当前是一个配置类

  • @ComponentScan 包扫描

  • @EnableAutoConfiguration

@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {}

(1)@AutoConfigurationPackage 自动配置包

@Import(AutoConfigurationPackages.Registrar.class)//给容器中导入组件
public @interface AutoConfigurationPackage {}
//利用Register给容器中导入一系列组件
    static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {

		//AnnotationMetadata:注解(AutoConfigurationPackage)元信息
		@Override
		public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
            //利用注解元信息获取包名,将包名封装到一个数组中
			register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));
		}

		@Override
		public Set<Object> determineImports(AnnotationMetadata metadata) {
			return Collections.singleton(new PackageImports(metadata));
		}

	}

MainApplication 所在包下

(2)@Import(AutoConfigurationImportSelector.class)

@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
   if (!isEnabled(annotationMetadata)) {
      return NO_IMPORTS;
   }
   AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
   return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}

1.利用getAutoConfigurationEntry(annotationMetadata);给容器中批量导入一些组件

2.利用List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);获取所有需要导入导入到容器中的组件(127个组件)

3.利用工厂加载得到所有组件

List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
      getBeanClassLoader());
Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {

4.从META-INF/spring.factories位置来加载一个文件。

默认扫描我们当前系统里面所有META-INF/spring.factories位置的文件

spring-boot-autoconfigure-2.3.4.RELEASE.jar包里面也有META-INF/spring.factories

文件里面写死了spring-boot一启动就要给容器中加载的所有配置类

spring-boot-autoconfigure-2.3.4.RELEASE.jar/META-INF/spring.factories

2、按需开启自动配置项

虽然我们127个场景的所有自动配置启动的时候默认全部加载。

xxxxAutoConfiguration 按照条件装配规则(@Conditional),最终会按需配置。

3、修改默认配置

    @Bean
    @ConditionalOnBean(MultipartResolver.class)  //容器中有这个类型组件
	//容器中没有这个名字 multipartResolver 的组件
    @ConditionalOnMissingBean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME) 
    public MultipartResolver multipartResolver(MultipartResolver resolver) {
            //给@Bean标注的方法传入了对象参数,这个参数的值就会从容器中找
            //SpringMVC multipartResolver。防止有些用户配置的文件上传解析器不符合规范
      // Detect if the user has created a MultipartResolver but named it incorrectly
      return resolver;
    }
给容器中加入了文件上传解析器;

SpringBoot默认会在底层配好所有的组件。但是如果用户自己配置了以用户的优先

@Bean
  @ConditionalOnMissingBean
  public CharacterEncodingFilter characterEncodingFilter() {
    }

总结:

  • SpringBoot先加载所有的自动配置类 xxxxxAutoConfiguration

  • 每个自动配置类按照条件进行生效,默认都会绑定配置文件指定的值。xxxxProperties里面拿。xxxProperties和配置文件进行了绑定

  • 生效的配置类就会给容器中装配很多组件

  • 只要容器中有这些组件,相当于这些功能就有了

  • 定制化配置

    • 用户直接自己@Bean替换底层的组件
    • 用户去看这个组件是获取的配置文件什么值就去修改。application.properties

xxxxxAutoConfiguration —> 组件 —> xxxxProperties里面拿值 ----> application.properties

5、最佳实践
  • 查看自动配置了哪些

    • 自己分析,引入场景对应的自动配置一般都生效了
    • 配置文件中debug=true开启自动配置报告。Negative(不生效)\Positive(生效)
  • 是否需要修改

    参照文档修改配置项 https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html#common-application-properties

    自己分析。xxxxProperties绑定了配置文件的哪些。

  • 自定义加入或者替换组件

  • @Bean、@Component。。。

  • 自定义器 XXXXXCustomizer

四、开发小技巧

1、Lombok

简化JavaBean开发

1.引入依赖
<dependency>
       <groupId>org.projectlombok</groupId>
       <artifactId>lombok</artifactId>
</dependency>
2.settings下安装插件
@Data//get set
@ToString//toString
@AllArgsConstructor//有参构造器
@NoArgsConstructor//无参构造器

@EqualsAndHashCode//重写HashCode
2、dev-tools
项目或者页面修改以后:Ctrl+F9;
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <optional>true</optional>
</dependency>
3、spring initializr

项目初始化向导

创建项目结构 依赖 主程序类

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值