JavaWeb合集10-StringBoot原理

十、StringBoot原理

1、配置优先级

SpringBoot中支持三种格式的配置文件:①application. properties;②application.yml ;③application.yaml

配置优先级:properties > yml > yaml

SpringBoot除了支持配置文件属性配置,还支持Java系统属性和命令行参数的方式进行属性配置。


注意:Springboot项目进行打包时,需要引入插件spring-boot-maven-plugin (基于官网骨架创建项目,会自动添加该插件)

2、Bean管理

2.1 从IOC容器中获取Bean对象

默认情况下,Spring项目启动时,会把bean都创建好放在IOC容器中,如果想要主动获取这些bean,可以通过如下:

  1. 根据名字获取Bean

    java 复制代码
    Object getBean(String  name)
  2. 根据类型获取Bean

    java 复制代码
    <T> T  getBean(Class<T>  requiredType)
  3. 根据name获取bean ( 带类型转换)

    java 复制代码
    <T>  T  getBean (String  name , Class<T> requiredType)
java 复制代码
@SpringBootTest
class MybatisTestApplicationTests {

    @Autowired
   private ApplicationContext applicationContext;  //注入IOC容器对象

    @Test
    void  getBean(){

        //通过IOC对象调用方法获取对应的Bean对象
        //1、根据Bean名称获取Bean对象(如果没有指定Bean对象名称,那么默认就是类名首字母小写).返回类型是Object需要强转
        UserController uc1= (UserController) applicationContext.getBean("userController");
        System.out.println(uc1);

         //2、根据Bean的类型来获取Bean对象
        UserController uc2=applicationContext.getBean(UserController.class);
        System.out.println(uc2);

        //3、根据name获取bean ( 带类型转换)
        UserController uc3=applicationContext.getBean("userController",UserController.class);
        System.out.println(uc3);
    }
}

注意:上述所说的[Spring项目启动时, 会把其中的bean都创建好] 还会受到作用域及延迟初始化影响,这里主要针对于默认的单例非延迟加载的bean而言。

2.2 Bean的作用域

Spring支持五种作用域,后三种在web环境才生效:

作用域 说明
singleton 容器内 同名称的Bean只有一个实例(单例) 默认
prototype 每次使用Bean时都会创建新的实例(非单例)
request 每个请求范围内都会创建新的实例(web环境中,了解)
session 每个会话范围内都会创建新的实例(web环境中,了解)
application 每个应用范围内会创建新的实例(web环境中,了解)
  1. 默认情况下Bean的初始化是在项目启动的时候进行的,不过在对应类上使用注解:@Lazy (懒惰的),可以使Bean的初始化延迟到获取Bean对象的时候才进行初始化。
  2. 在对应类上使用注解:@Scope("作用域") 来设置作用域的类型:如:@Scope("prototype")
  3. 实际开发当中,绝大部分的Bean是单例的,也就是说绝大部分Bean不需要配置scope属性。
java 复制代码
@Scope("prototype")
@RestController 
@RequestMapping("/users")
public class UserController {
}
2.3 第三方Bean的配置

需要下载第三方的jar包时,通常都是只读的,无法在其中加@Component注解,加类交给IOC容器管理。

这时就可以使用注解:@Bean 如果要管理的bean对象来自于第三方(不是自定义的) , 是无法用@Component及衍生注解声明bean的,就需要用到@Bean注解。

若要管理的第三方bean对象,建议对这些bean进行集中分类配置,可以通过@Configuration注解声明一个配置类。

java 复制代码
//定义一个配置类
@Configuration
public class CommonConfig {
@Bean   //将方法返回值交给IOC容器管理,成为IOC容器的bean对象
       //通过@Bean注解的name/value,属性指定bean名称,如果未指定,默认是方法名
public SAXReader saxReader(){
return new SAXReader();
   }
}
//如果要使用,直接使用@Autowird 注入就行

如果想要在方法中进行注入对应的Bean,那么直接使用形参的方式来注入:

java 复制代码
//定义一个配置类
@Configuration
public class CommonConfig {
@Bean  
    //根据形参自动注入userController对象
public SAXReader saxReader(UserController userController){
    System.out.println(userController)
  return new SAXReader();
   }
}

注意:

  1. 通过@Bean注解的name或value属性可以声明bean的名称,如果不指定,默认bean的名称就是方法名。
  2. 如果第三方bean需要依赖其它bean对象,直接在bean定义方法中设置形参即可,容器会根据类型自动装配。

3、SpringBoot原理

3.1 起步依赖原理

通过Maven的依赖传递的特性来进行自动依赖的导入,意思就是导入很少的依赖,就可以依次导入他们相关联的依赖。

3.2 自动配置原理

SpringBoot的原理就是,自动配置的原理,也就是如何将jar包中的配置类、Bean交给IOC容器管理的。

SpringBoot的自动配置就是当spring容器启动后,一些配置类、bean对象就自动存入到了I0C容器中,不需要我们手动去声明,从而简化了开发,省去了繁琐的配置操作。

3.2.1 @ComponentScan组件扫描

在项目中不是所有被导入的依赖加上对应的配置Bean都会交给IOC容器管理,在启动类中:@SpringBootApplication会进行扫描,默认只有在该项目包中的依赖才会被扫描到,并且加入到IOC容器中。不过可以在启动类中使用注解:@ServletComponentScan 来配置扫描包的范围。

java 复制代码
@ComponentScan( {"com.examp1e", " com.yhzy"})
@SpringBootApplication
public class SpringbootWebConfig2Application {
}
3.2.1 @lmport导入

使用@Import导入的类会被Spring加载到IOC容器中,导入形式主要有以下几种:普通类、配置类、ImportSelector接口实现类;@EnableXxxx注解,封装@Import注解

java 复制代码
@Import ({TokenParser.class}) //导入普通类,交给IOC容器管理
@Import ({HeaderConfig.class}) //导入配置类,交给IOC容器管理
@Import ( {MyImportSelector.class}) //导入ImportSelector接口实现类
@SpringBootApplication
public class SpringbootWebCon fig2Appl ication {
public static void main (String[] args) {
SpringApp1ication.run(SpringbootWebConfig2Application.class, args) ;
}
}
3.2.2 @Conditional

作用:按照一定的条件进行判断, 在满足给定条件后才会注册对应的bean对象到Spring I0C容器中。

位置:方法、类

@Conditional 本身是一个父注解,派生出大量的子注解:

@ConditionalOnClass: 判断环境中是否有对应字节码文件,才注册bean到IOC容器。

@ConditionalOnMissingBean:判断环境中没有对应的bean (类型或名称),才注册bean到IOC容器。

@ConditionalOnProperty:判断配置文件中有对应属性和值,才注册bean到IOC容器。

java 复制代码
@Configuration
public class HeaderConfig {
    
@Bean 
@Conditional0nClass (name= "io.jsonwebtoken.Jwts") //环境中存在指定的这个类,才会将该bean加入IOC容器中

public HeaderParser headerParser () {
return new HeaderParser() ;
}
@Bean
@ConditionalOnMissingBean //不存在该类型的bean,才会将该bean加入IOC容器中 --- 指定类型(value属性)或名称(name属性)
 @ConditionalOnProperty (name="name" havingValue="yhzy")//配置文件中存在指定的属性与值, 才会将该bean加入IOC容器中
public HeaderGenerator headerGenerator() {
return new HeaderGenerator() ;
}
}                                      
3.3 自定义starter

在实际开发中,经常会定义一些公共组件,提供给各个项目团队使用。而在SpringBoot的项目中 ,一般会将这些公共组件封装为SpringBoot的starter。

案例:

需求:自定义aliyun-oss-spring-boot-starter, 完成阿里云0SS操作工具类AliyunOSSUtils的自动配置。

目标:引入起步依赖引入之后,要想使用阿里云0SS,注入AliyunOSSUtils直接使用即可。

实现步骤:

  1. 创建aliyun-oss-spring-boot-starter模块(主要作用依赖管理)
  2. 创建aliyun-oss-spring-boot-autoconfigure模块,在starter中引入该模块
  3. 在aliyun-oss-spring-boot-autoconfigure模块中的定义自动配置功能,并定义自动配置文件META-INF/spring/ xxxx.imports

具备实现步骤如下:

一、创建aliyun-oss-spring-boot-starter模块

1、按照规范创建对应的项目,不需要提前选择任何依赖。

2、删不需要文件和目录,只保留 (.iml 和pom.xml文件)

3、清理pom.xml 里面不需要的依赖(后面需要引入创建的aliyun-oss-spring-boot-autoconfigure依赖)

xml 复制代码
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.6</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-oss-spring-boot-starter</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <url/>
    <licenses>
        <license/>
    </licenses>
    <developers>
        <developer/>
    </developers>
    <scm>
        <connection/>
        <developerConnection/>
        <tag/>
        <url/>
    </scm>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
    </dependencies>
    
</project>

二、创建aliyun-oss-spring-boot-autoconfigure模块,在starter中引入该模块(需要web开发依赖)

1、创建对应模块,将除sec目录和.iml、配置文件、pom.xml文件删除;将src下的启动类和测试类也删除

2、将pom文件中无用的依赖进行删除,并去aliyun-oss-spring-boot-starter模块的依赖文件中引入该模块

xml 复制代码
 <dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-oss-spring-boot-autoconfigure</artifactId>
</dependency>

三、在aliyun-oss-spring-boot-autoconfigure模块中的定义自动配置功能

1、引用阿里云OSS相关依赖

xml 复制代码
 <!--        阿里云OSS-->
        <dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-sdk-oss</artifactId>
            <version>3.17.4</version>
        </dependency>
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.3.1</version>
        </dependency>
        <dependency>
            <groupId>javax.activation</groupId>
            <artifactId>activation</artifactId>
            <version>1.1.1</version>
        </dependency>
        <!-- no more than 2.3.3-->
        <dependency>
            <groupId>org.glassfish.jaxb</groupId>
            <artifactId>jaxb-runtime</artifactId>
            <version>2.3.3</version>
        </dependency>

2、将阿里云OSS的工具类和参数实体类导入进来,并进行修改

java 复制代码
package com.aliyun.oss;

import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.util.UUID;

//将类交给IOC容器管理(这样就用于去创建对象来调用其方法了)
//@Component
//通过样例将OSS打造为一个工具类
public class AliyunOSS {
    // Endpoint以华北2(北京)为例,其它Region请按实际情况填写。 概括->外网访问
//    @Value("${aliyun.oss.endpoint}")
//    private String endpoint;
//    // 填写Bucket名称,例如examplebucket。
//    @Value("${aliyun.oss.bucketName}")
//    private String bucketName;



    private  AliOSSProperties aliOSSProperties;

    public AliOSSProperties getAliOSSProperties() {
        return aliOSSProperties;
    }

    public void setAliOSSProperties(AliOSSProperties aliOSSProperties) {
        this.aliOSSProperties = aliOSSProperties;
    }


    //文件上方法(返回上传后文件的访问路径)
    public  String upload(MultipartFile file) throws Exception {

        //获取阿里云oss参数
        String endpoint = aliOSSProperties.getEndpoint() ;
        String bucketName = aliOSSProperties.getBucketName () ;



        // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();

        //1、获取上传文件的输入流
        InputStream inputStream=file.getInputStream();

        //2、避免覆盖,生成UUID作为文件名
        String fileFullName=file.getOriginalFilename();
        String fileName= UUID.randomUUID().toString()+fileFullName.substring(fileFullName.lastIndexOf("."));

        // 上传到OSS
        OSS ossClient=new OSSClientBuilder().build(endpoint,credentialsProvider);
        ossClient.putObject(bucketName,fileName,inputStream);

        //获取文件上传后的路径:https://bucket的名字.地区的路径/文件名字
        String url=endpoint.split("//")[0]+"//"+bucketName+"."+endpoint.split("//")[1]+"/"+fileName;
        //关闭 ossClient
        ossClient.shutdown();

        //返回文件访问的路径
        return url;
    }

    //文件上方法(返回上传后文件的访问路径)
    public  String update(MultipartFile file,String filePath) throws Exception {

        //获取阿里云oss参数
        String endpoint = aliOSSProperties.getEndpoint() ;
        String bucketName = aliOSSProperties.getBucketName () ;


       // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();

        //1、获取上传文件的输入流
        InputStream inputStream=file.getInputStream();

        //2、从文件路径中截取出文件名,使其覆盖远有我文件,达到修改的效果。
        String fileName =filePath.substring(filePath.lastIndexOf("/")+1);

        // 上传到OSS
        OSS ossClient=new OSSClientBuilder().build(endpoint,credentialsProvider);
        ossClient.putObject(bucketName,fileName,inputStream);

        //关闭 ossClient
        ossClient.shutdown();

        //返回文件访问的路径
        return fileName;
    }
}
java 复制代码
//  AliOSSProperties配置参数实体类
@ConfigurationProperties(prefix = "aliyun.oss")
public class AliOSSProperties {
  private  String endpoint;
  private String bucketName;

    public String getEndpoint() {
        return endpoint;
    }

    public void setEndpoint(String endpoint) {
        this.endpoint = endpoint;
    }

    public String getBucketName() {
        return bucketName;
    }

    public void setBucketName(String bucketName) {
        this.bucketName = bucketName;
    }
}

3、在目录aliyun\oss创建一个配置类,并配置对应的工具类对象

java 复制代码
//配置类
@Configuration
@EnableConfigurationProperties(AliOSSProperties.class) //将AliOSSProperties其交给IOC管理
public class AliOSSAutoConfiguration {

    //外部Bean对象
    @Bean
    //注入对象直接通过参数形式
    public AliyunOSS  aliyunOSS(AliOSSProperties aliOSSProperties){
        AliyunOSS aliyunOSS=new AliyunOSS();
         aliyunOSS.setAliOSSProperties(aliOSSProperties);
        return aliyunOSS;
    }
}

4、在resource目录下创建目录META-INF\spring,并在创建的目录下创建名为(org.springframework.boot.autoconfigure.AutoConfiguration.imports)的文件

org.springframework.boot.autoconfigure.AutoConfiguration.imports文件内容:是自动配置类的全类名

txt 复制代码
com.aliyun.oss.AliOSSAutoConfiguration

四、测试

1、创建一个测试模块,导入web依赖、lombok依赖和创建的阿里云oss-starter依赖

xml 复制代码
     <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-oss-spring-boot-starter</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>

2、在yml配置文件中填写oss的配置

yml 复制代码
#阿里云OSS配置
aliyun:
  oss:
    endpoint: https://oss-cn-beijing.aliyuncs.com
    bucketName: yhzy-resource

3、创建Controller层,并写一POST接口,注入阿里云OSS的bean对象,通过接口测试工具对其测试

java 复制代码
@RestController
@RequestMapping("/upload")
public class Upload {

    @Autowired
    private AliyunOSS aliyunOSS;

    @PostMapping
    public String  upload(MultipartFile file) throws Exception {

       String path= aliyunOSS.upload(file);
        return path;
    }
}
相关推荐
一只叫煤球的猫7 小时前
写代码很6,面试秒变菜鸟?不卖课,面试官视角走心探讨
前端·后端·面试
bobz9657 小时前
tcp/ip 中的多路复用
后端
bobz9657 小时前
tls ingress 简单记录
后端
皮皮林5518 小时前
IDEA 源码阅读利器,你居然还不会?
java·intellij idea
你的人类朋友8 小时前
什么是OpenSSL
后端·安全·程序员
bobz9659 小时前
mcp 直接操作浏览器
后端
前端小张同学11 小时前
服务器部署 gitlab 占用空间太大怎么办,优化思路。
后端
databook11 小时前
Manim实现闪光轨迹特效
后端·python·动效
武子康12 小时前
大数据-98 Spark 从 DStream 到 Structured Streaming:Spark 实时计算的演进
大数据·后端·spark
该用户已不存在12 小时前
6个值得收藏的.NET ORM 框架
前端·后端·.net