SpringBoot2基础入门 学习(一)

2024-08-06 13:57:35 浏览数 (2)

SpringBoot2 基础入门

SpringBoot 简介

JavaEE开发的**一站式**解决方案! 简化Spring应用开发的一个框架,整个Spring技术栈的一个大整合;

SpringBoot时代背景

微服务

2014 ,martin fowler马丁·福勒

提出的:微服务架构**风格** 常听的:分布式微服务

优点: 一个应用拆分为一组小型服务 每一个服务: 运行在自己的进程内,也就是可独立部署和升级,通过HTTP的方式进行互通; • 服务围绕业务功能拆分 • 可以由全自动部署机制独立部署 • 去中心化,服务自治。服务可以使用不同的语言、不同的存储技术; 只要实现功能即可~

上图:**微服务分布式架构,每一个点表示一个功能, 使用时只需要调用需要的功能模块组合即可!**

缺点:

  • 运维要求高: 更多的服务意味着要投入更多的运维。
  • 分布式固有的复杂性: 使用微服务构建的是分布式系统。对于一个分布式系统,系统容错、网络延迟、 分布式事务等都会带来巨大的问题。
  • 接口调整成本高: 微服务之间通过接口进行通信。 如果修改某一个微服务的API,可能所有用到这个接口的微服务都需要进行调整。 远程调用、服务发现、负载均衡、服务容错、配置管理、服务监控、链路追踪、日志管理、任务调度……

说到微服务架构,不得不提的就是 单体应用

单体应用

一个归档包(可以是JAR、WAR、EAR或其它归档格式)包含所有功能的应用程序,通常称为**单体应用。**

优点

  • 便于共享: 单个归档文件包含所有功能,便于在团队之间以及不同的部署阶段之间共享。
  • 易于测试: 单体应用一旦部署,所有的服务或特性就都可以使用了,这简化了测试过程。 因为没有额外的依赖,每项测试都可以在部署完成后立刻开始。
  • 易于部署: 只需将单个归档文件复制到单个目录下。

缺点

  • 复杂性高: 由于是单个归档文件,所以一个文件 等于 整个项目,文件包含的模块非常多,导致模块的边界模糊。 依赖关系不清晰、代码的质量参差不齐,混乱的堆在一起,使得整个项目非常复杂。 以致每次修改代码,都非常小心,可能添加一个简单的功能,或者修改一个Bug都会带来隐藏的缺陷。
  • 技术债务: 随着时间的推移、需求的变更和技术人员的更替,会逐渐形成应用程序的技术债务,并且越积越多。
  • 扩展能力受限: 单体应用只能作为一个整体进行扩展,无法根据业务模块的需要进行伸缩。 (为了提高项目性能可以, 将一个项目复制多份部署多台服务器~)
  • 阻碍技术创新: 对于单体应用来说,技术是在开发之前经过慎重评估后选定的, 每个团队成员都必须使用相同的开发语言、持久化存储及消息系统。

SpringBoot2入门

环境约束

Java8 或以上 学习

Maven3.3 或以上 学习

本人使用的编辑器是: Idea2020 或其它编辑器,Spring官方的推荐的 STS

maven设置

settings.xml 文件修改配置~ Maven——conf目录下:

代码语言:javascript复制
 <!-- 
<!-- 阿里云仓库:提供大量组件,不配置自己联网下载到本地仓库~ --> 
  <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>
 <!-- 告诉Maven统一编辑项目 jdk1.8~ -->
  <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>

什么是SpringBoot

Springboot是用于简化原始Spring的复杂 快速创建出生产级别的Spring应用,也是Spring技术栈的一站式框架。 本质上还是Spring,只不过将以往需要配置的信息封装到底层,使开发者更加快捷的搭建好环境。 因此被称为Spring的**脚手架**:

  • 脚手架指的是两种技术之一: 第一种是与某些MVC 框架中的数据库访问相关的代码生成技术; 第二种是由各种工具支持的项目生成技术。

SpringBoot的优点

内嵌Web服务器 创建独立的Spring应用 无代码生成,无需编写XML 自动starter以来,简化构建配置 自动配置Spring以及第三方功能 提供生产级别的监控、健康检查以及外部化配置

SpringBoot缺点

人称版本帝,迭代快,需要时刻关注变化 封装太深,内部原理复杂,不容易精通


正片开始

好了,从现在开始我们可以迅速创建一个SpringBoot应用,

可以通过IDEA的快捷配置方式

同时也可以使用Maven直接配置,在这里只演示第二种方式。

HelloWorld!!

需求:浏览发送/hello请求,响应 Hello, Spring Boot 2

1.创建maven工程

引入依赖:

pom.xml

代码语言:javascript复制
<!-- 集成一个父项目 -->	
	<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.6.RELEASE</version>
    </parent>
    
<!-- spring-boot对一些开发所需的资源Jar有自动的管理都存在在对应的 starter-xxx管理.
	 这里使用 spring-boot-starter-web 引入所有的web组件!
	 一切都由SpringBoot帮你做好了。
 -->	
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

2.创建主程序

SpringBoot程序需要一个入口: 负责启动开启应用程序

  • 主程序类一般声明在最外层包下,默认扫描所在包下的所有类注解 方便初始化应用!
  • 这里提到很多新的注解,之前常用的MVC 注解依然可以使用, 根据喜好使用 可以多学习了解~
代码语言:javascript复制
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication  //标注主程序类,这是一个Springboot应用! 
//@SpringBootApplication(scanBasePackages = "指定扫描包下注解~") 	//默认扫描该类的包及子包~
public class SpringBootRun {
    public static void main(String[] args) {
        //用来执行开启SpringBoot程序;                                 参数当前主程序类.class  args
        ConfigurableApplicationContext run = SpringApplication.run(SpringBootRun.class,args);
    }
}

3.创建Controller控制器:

代码语言:javascript复制
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

//作用:该类是一个Controller控制器 且 下所有方法的返回值为一个JSON
//相当于是一个:@Controller 和 @ResponseBody 注解的集合,内部SpringBoot 自定义了完善的属性配置,当然也可以通过配置修改覆盖...
@RestController
public class HelloController {
    //相当于: 以前SpringMVC的 @RequestMapping get方式请求~
    //@RequestMapping(value = "/show" ,method = RequestMethod.GET)
    @GetMapping(value = "/show")    //@GetMapping用于处理请求方法的GET类型,@PostMapping用于处理请求方法的POST类型等。
    public String Hello(){
        return "Hello Wrod!!";
    }
}

4. 启动主程序类:

每错直接启动即可:SpringBoot中有自带的集成运行环境容器;

可以清除的看到 Tomcat initialized with port(s): 8080 (http)

或打包控制台——部署运行(简化部署):

使用Maven 打包程序:

pom.xml 文件中加入

代码语言:javascript复制
   <!-- 使SpringBoot工程支持,项目打成jar包,直接在目标服务器执行即可 -->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.2.6.RELEASE</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

ok, 到这基本体现到 SpringBoot 应用程序的强大! 无须服务器!单体项目~ 强大注解生态资源自带集成~!!

SpringBoot特点

以下说明全部来源于 大佬!! 本人借鉴学习!

依赖管理

SpringBoot 对依赖管理非常强大!

在Spring Boot入门程序中,项目pom.xml文件有两个核心依赖~

分别是spring-boot-starter-parentspring-boot-starter-web 关于这两个依赖的相关介绍具体如下。

spring-boot-starter-parent

举例说明:**pom.xml**

代码语言:javascript复制
<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.6.RELEASE</version>
</parent>
  • 上述代码中,将spring-boot-starter-parent依赖作为Spring Boot项目的统一父项目依赖管理 并将项目版本号统一为2.1.6.RELEASE,该版本号根据实际开发需求是可以修改的。
  • 使用**Ctrl 鼠标左键**进入并查看spring-boot-starter-parent底层源文件:
  • 发现spring-boot-starter-parent的底层有一个父依赖**spring-boot-dependencies**,核心代码具体如下。
代码语言:javascript复制
<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-dependencies</artifactId>
  <version>2.1.3.RELEASE</version>
  <relativePath>../../spring-boot-dependencies</relativePath>
</parent>
...

继续查看spring-boot-dependencies底层源文件,核心代码具体如下。

代码语言:javascript复制
<properties>
  <activemq.version>5.15.8</activemq.version>
  ...
  <solr.version>7.4.0</solr.version>
  <!-- Spring家族依赖组件~ -->
  <spring.version>5.1.5.RELEASE</spring.version>
  <spring-amqp.version>2.1.4.RELEASE</spring-amqp.version>
  <spring-batch.version>4.1.1.RELEASE</spring-batch.version>
  <spring-cloud-connectors.version>2.0.4.RELEASE</spring-cloud-connectors.version>
  <spring-data-releasetrain.version>Lovelace-SR5</spring-data-releasetrain.version>
  <spring-framework.version>${spring.version}</spring-framework.version>
  <spring-security.version>5.1.4.RELEASE</spring-security.version>
  <spring-session-bom.version>Bean-SR3</spring-session-bom.version>
  <spring-ws.version>3.0.6.RELEASE</spring-ws.version>
  <sqlite-jdbc.version>3.25.2</sqlite-jdbc.version>
  <statsd-client.version>3.1.0</statsd-client.version>
  <sun-mail.version>${javax-mail.version}</sun-mail.version>
  <thymeleaf.version>3.0.11.RELEASE</thymeleaf.version>
  <tomcat.version>9.0.16</tomcat.version>				<!-- Tomcat -->
  <unboundid-ldapsdk.version>4.0.9</unboundid-ldapsdk.version>
  <undertow.version>2.0.17.Final</undertow.version>
  <versions-maven-plugin.version>2.7</versions-maven-plugin.version>
  <webjars-hal-browser.version>3325375</webjars-hal-browser.version>
  <webjars-locator-core.version>0.35</webjars-locator-core.version>
</properties>
  • 从**spring-boot-dependencies**底层源文件可以看出 该文件通过< properties >标签对一些常用技术框架的依赖文件进行了统一版本号管理, 例如 activemq、spring、tomcat等,都有与Spring Boot 2.1.3版本相匹配的版本, 这也是pom.xml引入依赖文件不需要标注依赖文件版本号的原因。
  • 需要说明的是,如果pom.xml引入的依赖文件不是 spring-boot-starter-parent管理的,
  • 那么在pom.xml引入依赖文件时,需要使用 < version > 标签指定依赖文件的版本号。

开发中见到很多:**见到很多 spring-boot-starter-***

spring-boot-starter-web 依赖

spring-boot-starter-parent父依赖启动器的主要作用是进行版本统一管理:

那么项目运行依赖的JAR包是从何而来?又是怎样管理的呢?

下面,查看项目pom.xml文件中的spring-boot-starter-web依赖。

查看**spring-boot-starter-web**依赖文件源码,核心代码具体如下。

代码语言:javascript复制
<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <version>2.1.3.RELEASE</version>
    <scope>compile</scope>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-json</artifactId>
    <version>2.1.3.RELEASE</version>
    <scope>compile</scope>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
    <version>2.1.3.RELEASE</version>
    <scope>compile</scope>
  </dependency>
  <dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.0.14.Final</version>
    <scope>compile</scope>
  </dependency>
  <!-- .... -->
</dependencies>

spring-boot-starter-web依赖启动器的主要作用:

  • 是提供Web开发场景所需的底层所有依赖文件, 它对Web开发场景所需的依赖文件进行了统一管理。
  • 正是如此,在pom.xml中引入spring-boot-starter-web依赖启动器时,就可以实现Web场景开发 不需要额外导入Tomcat服务器以及其他Web依赖文件等。 当然,这些引入的依赖文件的版本号还是由spring-boot-starter-parent父依赖进行的统一管理。

Spring Boot除了提供有上述介绍的Web依赖启动器外,还提供了其他许多开发场景的相关依赖,我们可以打开Spring Boot官方文档,搜索“Starters”关键字查询场景依赖启动器,具体如下图所示。

@SpringBootApplication注解 自动装配原理

@SpringBootApplication注解表示Spring Boot启动类。

  • Spring Boot应用的启动入口是@SpringBootApplication注解标注类中的main()方法 @SpringBootApplication能够扫描Spring组件并自动配置Spring Boot
  • 查看@SpringBootApplication注解源码 :
  • 按住: Ctrl @SpringBootApplication
代码语言:javascript复制
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
//以上一些Java的注解无伤大雅!
@SpringBootConfiguration     // 标明该类为配置类
@EnableAutoConfiguration     // 启动自动配置功能
@ComponentScan(              // 包扫描器
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
...
}

@SpringBootApplication注解是一个组合注解:

包含@SpringBootConfiguration@EnableAutoConfiguration@ComponentScan三个核心注解

@SpringBootConfiguration注解

@SpringBootConfiguration注解表示类为: Spring Boot配置类

代码语言:javascript复制
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
}

@SpringBootConfiguration注解内部有一个核心注解@Configuration

  • Spring框架提供的注解: 表示当前类为一个配置类(XML配置文件的注解表现形式)
  • 并可以被组件扫描器扫描。 由此可见,@SpringBootConfiguration注解的作用与@Configuration注解相同
  • 都是标识一个可以被组件扫描器扫描的配置类, 只不过@SpringBootConfiguration是被Spring Boot进行了重新封装命名而已。
@EnableAutoConfiguration注解

@EnableAutoConfiguration注解表示开启自动配置功能

该注解是Spring Boot框架最重要的注解,也是实现自动化配置的注解。

代码语言:javascript复制
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage                             // 自动配置包
@Import({AutoConfigurationImportSelector.class}) // 自动配置类扫描导入
public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
    Class<?>[] exclude() default {};
    String[] excludeName() default {};
}

@EnableAutoConfiguration注解也是一个组合注解,

它主要包括有@AutoConfigurationPackage@Import两个核心注解。

自己查看以下注解 Ctrl

  • @AutoConfigurationPackage: @AutoConfigurationPackage注解的功能是由@Import注解实现的, 作用是向容器导入注册的所有组件,导入的组件由Registrar决定
  • @Import({AutoConfigurationImportSelector.class}):  使用了这个注解,相当于 Java 中的 import 关键字,可以导入 Spring 的 bean 到 IOC 容器中。

@AutoConfigurationPackage:类

自动配置包?指定了默认的包规则

代码语言:javascript复制
@Import(AutoConfigurationPackages.Registrar.class)  //给容器中导入一个组件
public @interface AutoConfigurationPackage {}
 
//利用Registrar给容器中导入一系列组件
//将指定的一个包下的所有组件导入进来?MainApplication 所在包下。

查看AutoConfigurationImportSelector类的getAutoConfigurationEntry()方法,核心代码具体如下。

Ctrl F Idea查看文本

代码语言:javascript复制
protected AutoConfigurationImportSelector.AutoConfigurationEntry
        getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
 AnnotationMetadata annotationMetadata) {
  if (!this.isEnabled(annotationMetadata)) {
    return EMPTY_ENTRY;
  } else {
    AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
         // 获取所有Spring Boot提供的后续自动配置类XxxAutoConfiguration
    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);
         // 筛选并过滤出当前应用环境下需要的自动配置类XxxAutoConfiguration
    configurations = this.filter(configurations, autoConfigurationMetadata);
    this.fireAutoConfigurationImportEvents(configurations, exclusions);
    return new AutoConfigurationImportSelector.AutoConfigurationEntry(
configurations, exclusions);
  }
}

在上述展示的getAutoConfigurationEntry()方法,

  • 其主要作用是筛选出当前项目环境需要启动的自动配置类XxxAutoConfiguration
  • 从而实现当前项目运行所需的自动配置环境。

另外,在上述核心方法中加粗显示了2个重要的业务处理方法,具体说明如下。

  • this.getCandidateConfigurations(annotationMetadata, attributes)方法: 该方法的主要作用是从Spring Boot提供的自动配置依赖的META-INF/spring.factories文件中 获取所有候选自动配置类XxxAutoConfiguration(2.1.3版本提供有121个自动配置类);
  • this.filter(configurations, autoConfigurationMetadata)方法: 该方法的作用是对所有候选的自动配置类进行筛选,根据项目pom.xml文件中加入的依赖文件筛选出 最终符合当前项目运行环境对应的自动配置类(筛选完成后可能只有25个)。

SpringBoot 提供的自动配置类

SpringBoot在启动的时候从自动配置类路径下的META-INF/spring.factorles中获取

EnableAutoConfiguration指定的值,并将这些值作为自动配置类导入到容器中,自动配置类就生效。

在项目中加入了Web环境依赖启动器

  • 对应的WebMvcAutoConfiguration自动配置类就会生效,打开该自动配置类会发现 在该配置类中通过全注解配置类的方式对Spring MVC运行所需环境进行了默认配置, 包括:默认前缀、默认后缀、视图解析器、MVC校验器等。
  • 而这些自动配置类的本质是传统Spring MVC框架中对应的XML配置文件
  • 只不过在Spring Boot中以自动配置类的形式进行了预先配置。
  • 因此,在Spring Boot项目中加入相关依赖启动器后,基本上不需要任何配置就可以运行程序,
  • 当然,我们也可以对这些自动配置类中默认的配置进行更改。
@ComponentScan注解

@ComponentScan注解是一个组件包扫描器,

其主要作用是扫描指定包及其子包下所有注解类文件作为Spring容器的组件使用。

okok, 就到这里了, 后面在深入研究~ 好累需要反复斟酌~


Spring常用注解使用分析:

@Configuration

相当于 Spring配置文件中的< beans>标签

告诉SpringBoot这是一个配置类,配置类本身也是组件 等于以前Spring项目的Sring配置文件.xml;

配置类里面使用@Bean标注在方法上给容器注册组件,默认也是单实例的 Full

另外注意,**被@configuration标注的类本身,也会作为一个bean注入到容器中的。**

Full模式与Lite模式

proxyBeanMethods:代理bean的方法

  • Full(proxyBeanMethods = true) 保证每个@Bean方法被调用多少次返回的组件都是单实例的
  • Lite(proxyBeanMethods = false) 每个@Bean方法被调用多少次返回的组件都是新创建的
  • 组件依赖必须使用Full模式默认。
@Bean

给容器中添加组件。

以方法名作为组件的 id。返回类型就是组件类型。返回的值,就是组件在容器中的实例;

Demo测试1

以上项目加一个包 com.wsm.entity

加一个 测试实体类 User.Java

代码语言:javascript复制
public class User {
    private int id=0;
    private String name="默认";
    //get/set
    //toString()....

加一个包 com.wsm.config

加入一个 配置类

ConfigXX.Java

代码语言:javascript复制
//配置类学习
@Configuration
public class ConfigXX {
    //Bean
    //就相当于以前的: <Bean></Bean>
    @Bean           //以方法名作为组件的id  返回类型就是组件类型。返回的值,就是组件在容器中的实例
    public String str(){
        return "字符";
    }
    @Bean("myUser") //指定组件id名,将该对象存储到spring的上下文中 (环境中)
    public User user() {
        User user = new User();
        user.setId(1);
        user.setName("张三");
        return user;
    }
    @Bean("tom")
    public User userTom(){
        User user = new User();
        user.setId(1);
        user.setName("tom");
        return user;
    }
}

主程序类SpringBootRun.Java

代码语言:javascript复制
@SpringBootApplication  //标注主程序类,这是一个Springboot应用!
public class SpringBootRun {
    public static void main(String[] args) {
        //用来执行开启SpringBoot程序;                                 参数当前主程序类.class  args
        ConfigurableApplicationContext run = SpringApplication.run(SpringBootRun.class,args);

        //查看容器里面所有的组件,Bean
        String[] names = run.getBeanDefinitionNames();
        System.out.println("-----------所有的组件Bean----------");
        for (String name : names) {
            //因为,有很多是默认的所以会有很多~
            System.out.println(name);
        }

        //从容器中根据id获取指定组件
        String str = (String)run.getBean("str");   //方法返回Object类型——》强制转换
        System.out.println(str);
        //查询Spring上下文存在该元素
        boolean isok = run.containsBean("str");
        System.out.println(isok);
        
        User myUser = (User)run.getBean("myUser");
        System.out.println(myUser);

        User tom1 = (User)run.getBean("tom");
        User tom2 = (User)run.getBean("tom");
        System.out.println(tom1==tom2);     //比较结果:true 结论@Configuration默认模式是Full 单例
    	//被@Configuration注解的类同时也被注入
        ConfigXX cfx = (ConfigXX)run.getBean(ConfigXX.class);
        System.out.println(cfx.user()==cfx.user());     //结果为true 调用new 的方法同样是true;
	}
}
@ImportResource 引入原生配置

以上的配置类 的使用, 刚开始学习时候有一点的不舒服~

SpringBoot 本质上是Spring的管理, 当然还是支持Spring的核心 IOC

也还可以使用以前的Spring配置文件来管理项目!

  • 使用 @ImportResource 引入原生配置

Demo测试2

Maven工程 resource资源目录下添加一个Sping配置文件:

beanConf.xml

代码语言:javascript复制
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="w" class="com.wsm.entity.User"></bean>
</beans>

主程序

代码语言:javascript复制
@SpringBootApplication                  //标注主程序类,这是一个Springboot应用!
@ImportResource("classpath:beanConf.xml")  //classpath表示就是资源目录下; 这里不多解释了...
public class SpringBootRun {
    public static void main(String[] args) {
        //用来执行开启SpringBoot程序;                                 参数当前主程序类.class  args
        ConfigurableApplicationContext run = SpringApplication.run(SpringBootRun.class,args);

        User user = (User) run.getBean("w");
        System.out.println(user);
    }
}
@import

声明在类上

这个注解在老版本SpringBoot1中,将他放在configuration 配置类上的时候

  • 只能完成引入别的configuration类的功能。类似于容器xml配置文件的import标签。

但是在新版本中,可以引入任何类,不一定是configuration类。

  • 这样就变得非常灵活。这里 的引入就是注入的意思。将该类注入到容器中,
  • 即使该类没有被注解@service, @controller,@repository, @component等所标注。

语法:

@import({注入类.class,多个类.class})

主程序类

代码语言:javascript复制
@SpringBootApplication                  //标注主程序类,这是一个Springboot应用!
@Import({User.class})
public class SpringBootRun {
    public static void main(String[] args) {
        //用来执行开启SpringBoot程序;                                 参数当前主程序类.class  args
        ConfigurableApplicationContext run = SpringApplication.run(SpringBootRun.class,args);

        User u = run.getBean(User.class);
        System.out.println(u);
    }
}

注意:

使用前要确保该类型确实不存在任何一个Spring管理Bean

不然:

@componentscan

这个注解主要是标注需要扫描哪些包路径。

该路径下标注了@service, @controller,@repository, @component的类,

都将被注入到容器中。除了这四个标签,包路径下标注了@configuration类,也会被注入到容器中。

@import 升级版本!

@Conditional 条件装配

声明在 配置类上!**@Configuration**

只有满足Conditional指定的条件,则进行 配置类组件注入!!!

实现动态配置 SpringBoot 的组件, 对一些组件进行判断则生成~

  • SpringBoot 底层配置了这么多的类不可能每次都全部加载!!
  • 底层就是采用该注解进行配置,是否存在使用依赖则执行底层类的注入大致原理有兴趣在研究~
  • 该注解的类型有很多…

Demo3测试3

修改ConfigXX.Java

代码语言:javascript复制
@Configuration
@ConditionalOnBean(name = "abc")    //检查上下文中是否存在abc,如果存在,才执行下面的所有的创建操作      
//@ConditionalOnMissingBean(name = "abc") 
//检查上下文中是否存在abc,如果没有存在,执行下面的所有的创建操作
public class ConfigXX {
    //Bean
    //就相当于以前的: <Bean></Bean>
    @Bean           //以方法名作为组件的id  返回类型就是组件类型。返回的值,就是组件在容器中的实例
    public String str(){
        return "字符";
    }
    @Bean("tom")
    public User userTom(){
        User user = new User();
        user.setId(1);
        user.setName("tom");
        return user;
    }
    @Bean("myUser") //指定组件id名,将该对象存储到spring的上下文中 (环境中)
    public User user() {
        User user = new User();
        user.setId(1);
        user.setName("张三");
        return user;
    }
}

分别执行主程序:

代码语言:javascript复制
@SpringBootApplication
public class SpringBootRun {
    public static void main(String[] args) {
        //用来执行开启SpringBoot程序;                                 参数当前主程序类.class  args
        ConfigurableApplicationContext run = SpringApplication.run(SpringBootRun.class,args);

        //查看容器里面所有的组件,Bean
        String[] names = run.getBeanDefinitionNames();
        System.out.println("-----------所有的组件Bean----------");
        for (String name : names) {
            //因为,有很多是默认的所以会有很多~
            System.out.println(name);
        }
    }
}

@ConditionalOnBean(name = “abc”) 存在执行

@ConditionalOnMissingBean(name = “tom”) 不存在执行

@ConfigurationProperties 配置绑定

在编写项目代码时,我们要求更灵活的配置,更好的模块化整合。

  • 在 Spring Boot 项目中,为满足以上要求,
  • 我们将大量的参数配置在 application.propertiesapplication.yml 文件中,
  • 通过 @ConfigurationProperties 注解,我们可以方便的获取这些参数值

application.properties和application.yml文件的区别

一般上来说,当我们创建一个SpringBoot项目时

,IDE会默认帮我们创建一个application.properties配置文件。有些朋友习惯把.properties文件改成.yml文件。

  • .properties文件,通过.来连接,通过=来赋值,结构上,没有分层的感觉,但比较直接。
  • .yml文件,通过:来分层,结构上,有比较明显的层次感,最后key赋值的:后需要留一个空格。
  • 执行顺序: 如果工程中同时存在application.properties文件和 application.yml文件 yml文件会先加载,而后加载的properties文件会覆盖yml文件。 所以建议工程中,只使用其中一种类型的文件即可。
@Component

声明在 @ConfigurationProperties 类上

@Component (把普通pojo实例化到spring容器中,相当于配置文件中的 ) 泛指各种组件,

就是说当我们的类不属于各种归类的时候 (不属于@Controller、@Services等的时候)

我们就可以使用@Component来标注这个类。

@EnableConfigurationProperties

@EnableConfigurationProperties注解的作用是: 使用 @ConfigurationProperties 注解的类生效。

  • 如果一个配置类只配置@ConfigurationProperties注解,而没有使用@Component 那么在IOC容器中是获取不到properties 配置文件转化的bean。
  • 说白了 @EnableConfigurationProperties 相当于把使用 @ConfigurationProperties 的类进行了一次注入。
  • @EnableConfigurationProperties 和 @Component 二者取其一

Demo测试.properties

com.wsm.entity包下加入 Student.Java

代码语言:javascript复制
//配置类注解,被自动扫描发现
//@Component
@ConfigurationProperties(prefix = "stu")                     //指明前缀
@PropertySource("classpath:application.properties")        //指明配置源文件位置
public class Student {
    private int id;
    private String name;
    //get/set/toString()....
}

resources目录下加入application.properties

代码语言:javascript复制
# 修改SpringBoot的端口 默认8080
server.port=9090     
#根据@ConfigurationProperties 声明类的前缀进行 .属性=值 注入;
stu.id=10001
stu.name=admin

#.properties文件
#键值注入 字符串不需要引号..

主程序:

代码语言:javascript复制
@SpringBootApplication
@EnableConfigurationProperties({Student.class})
public class SpringBootRun {
    public static void main(String[] args) {
        //用来执行开启SpringBoot程序;                                 参数当前主程序类.class  args
        ConfigurableApplicationContext run = SpringApplication.run(SpringBootRun.class,args);

        Student stu = run.getBean(Student.class);
        System.out.println(stu);
    }
}

Demo测试.yml

com.wsm.entity包下加入 Person.java

代码语言:javascript复制
@ConfigurationProperties(prefix = "person")
public class Person {
    private String userName;
    private Boolean boss;
    private Date birth;
    private Integer age;
    private User user;
    private String[] interests;
    private List<String> animal;
    private Map<String, Object> score;
    private Set<Double> salarys;
    //get/set/toString()
}
yml编写规范 学习

大小写敏感 使用缩进表示层级关系 缩进时不允许使用Tab键,只允许使用空格。 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可 YAML 支持的数据结构有三种

  • 对象:键值对的集合,又称为映射(mapping)/ 哈希(hashes) / 字典(dictionary)
  • 数组:一组按次序排列的值,又称为序列(sequence) / 列表(list)
  • 纯量(scalars):单个的、不可再分的值

一组键值对,使用冒号结构表示

键:值 :冒号后面必须跟着空格!! 一定要注意错误了不易检查!!

resources目录下加入application.yml

代码语言:javascript复制
person:
  userName: 张三
  boss: true
  birth: 2020/01/01 15:20:30
  age: 20
  user:                             #对象User类型
    id: 1001
    name: 张三
  interests: ['test01','test02']    #字符串数组
  animal:                           #字符串集合
  - cat                                 #字符串值
  - dog
  score:                            #Map类型 String,Object类型
    english:                          #Map元素键1
      first: 100                        #Map键1的值:又是一个Map类型
      last: 20
    math: [10,20,30,40]               #Map元素键2:也是一个Map类型
    chinese: {one: 50,two: 60,three: 70}
  salarys: [4555.5,4666.5,4777.5]

主程序:

代码语言:javascript复制
@SpringBootApplication
@EnableConfigurationProperties({Student.class, Person.class})
public class SpringBootRun {
    public static void main(String[] args) {
        //用来执行开启SpringBoot程序;                                 参数当前主程序类.class  args
        ConfigurableApplicationContext run = SpringApplication.run(SpringBootRun.class,args);

        Person person = run.getBean(Person.class);
        System.out.println(person);
    }
}

自动配置原理入门自定义

自动配置类的作用,配置注入功能组件自动完成。

根据上面的 SpringBoot的特定得知SpringBoot的底层就是大量的 自动配置类 SpringBoot2 128个

详情查看 @EnableAutoConfiguration注解

自定义 自动配置

pom.xml

代码语言:javascript复制
<!-- 加入依赖 -->
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.example</groupId>
    <artifactId>SpringBoot128</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
            <version>2.1.6.RELEASE</version>
        </dependency>
    </dependencies>
</project>

Spring Boot优化了很多配置的方式方法,

让我们少去了很多配置的环节。但又给了我们自定义配置的选择权。

在SpringBoot中会有许多的自带自动装配,

通常在启动时加载,如何实现自己定义的自动装配?我们需要三个 关键类:

属性读取类

该类的作用是读取hello开头的属性配置文件

读取值后会存入到容器中。默认值是Spring Boot

HelloProperties.Java

代码语言:javascript复制
@Component
@ConfigurationProperties(prefix = "hello")		//使用配置绑定 前缀hello
public class HelloProperties {
    private String msg = "SpringBoot";			
	//默认值 SpringBoot,如果引入自动配置的项目可以通过 .properties .yml 文件中,进行更改!						
    public String getMsg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }
}
核心事件类

该类主要处理 配置类要执行的主要功能!!

我们定义该类来将定义的msg加上hello前缀。

Hello.Java

代码语言:javascript复制
public class Hello {
    private  String msg;
    public String say(){	
        return  "hello" getMsg();		//打印输出Hello   msg
    }
    public String getMsg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }
}
整合类

整合类是最重要的类,它关系着前两个类的运作。

HelloAutoConfigration.Java

代码语言:javascript复制
@Configuration   //这是一个配置类
@ConditionalOnClass(Hello.class)    //是否存在 Hello的类,没有不执行类中操作...
@EnableConfigurationProperties(HelloProperties.class)   //开启使用 @ConfigurationProperties 注解的类生效。
@ConditionalOnProperty(prefix = "hello", value = "enabled", matchIfMissing = true)
//prefix 数组,获取property名称的前缀,可有可无
//name 数组,property完整名称或部分名称,与prefix组合使用组成完整属性名称,与value不可同时存在
//value 数组,获取property完整名称或部分名称,与prefix组合使用成完整属性名称,与name不可同时存在
//havingValue 比较获取的属性值与havingValue给定的值是否相同,相同才加载配置类
//matchIfMissing 缺少property时是否加载,如果为true,没有该property属性也会正常加载,反之报错。
//是否存在 hello 属性则执行下面操作..
public class HelloAutoConfigration {

    @Autowired
    private HelloProperties helloProperties;
    @Bean
    @ConditionalOnMissingBean
    public Hello createHello() {
        Hello hello = new Hello();
        hello.setMsg(helloProperties.getMsg());
        return hello;
    }
}

使用

将maven文件打包后加载入仓库

给要使用的类添加pom配置

在控制器输出

Controller

HelloController.Java

代码语言:javascript复制
import com.wsm.Hello;           //引入依赖的类型;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController  //@Controller @ResponseBody
public class HelloController {

    @Autowired
    private Hello hello;        //注入

    @GetMapping(value = "/showMsg")
    public String shoMsg(){
        return  hello.say();
    }
}
引入自定义配置依赖

pom.xml

代码语言:javascript复制
<!-- 引入自定义配置依赖 -->
<dependency>
    <groupId>org.example</groupId>
    <artifactId>SpringBoot128</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

0 人点赞