SpringBoot原理

一、配置优先级

Spring项目支持五种配置,分别是propertiesymlyaml系统参数配置命令行参数配置,现在我们要讨论它们的配置优先级

以项目运行的端口为例,分别在五种配置中配置不同的端口号,通过控制变量法研究五种配置的优先级,系统默认的端口为8080,即没有配置端口时运行的端口号

  • yamlyamlproperties三种配置文件的比较

在这里插入图片描述
在这里插入图片描述

  • yamlyml两种配置文件的比较

在这里插入图片描述

三种配置文件的优先级:properties > yml > yaml


  • 系统参数配置命令行参数配置 的比较

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

两种配置文件的优先级:命令行参数配置 > 系统参数配置


  • 总比较

在这里插入图片描述

结论:命令行参数配置 > 系统参数配置 > properties > yml > yaml



二、 Bean管理

2.1 获取bean

使用getBean()方法的前提是必须由IOC容器对象来调用,且必须是org.springframework.context.ApplicationContext 包下的类

在这里插入图片描述

方法描述
getBean(String name)通过bean的名字获取bean对象
getBean(Class <T> aClass)通过bean的类型获取bean对象
getBean(String name,Class <T> aClass)通过bean的名字和类型获取bean对象
@RestController
public class studentController {
    studentController(){
        System.out.println("构造器执行了~~~");
    }
}

@SpringBootTest
class SpringBootPrincipleApplicationTests {
    @Autowired
    private ApplicationContext context;

    @Test
    public void testGetBean(){
        // 通过名字获取bean对象
        Object bean1 = context.getBean("studentController");
        System.out.println(bean1);

        // 通过类型获取bean对象
        studentController bean2 = context.getBean(studentController.class);
        System.out.println(bean2);

        // 通过名字和类型获取bean对象
        studentController bean3 = context.getBean("studentController", studentController.class);
        System.out.println(bean3);
    }

}

在这里插入图片描述



2.2 bean的作用域

  • bean的作用域就是IOC容器创建时所管理的bean对象的状态,即这个bean是单例对象还是每次使用都会创建新的bean对象
bean作用域描述
singleton【重点】容器内同名称的bean只有一个,即这个bean为单例对象【默认状态】
prototype【重点】每次使用bean时会创建新的实例(非单例)
request每次请求范围内会创建新的实例【web环境中,了解】
session每次会话范围内会创建新的实例【web环境中,了解】
application每个应用范围内创建新的实例【web环境中,了解】
  • @Scope(singleton) 【默认的作用域】
@RestController
@Scope("singleton")
public class studentController {
    studentController(){
        System.out.println("构造器执行了~~~");
    }
}
@SpringBootTest
class SpringBootPrincipleApplicationTests {
    @Autowired
    private ApplicationContext context;

    @Test
   public void testScope(){
       for (int i = 0; i < 5; i++) {
           studentController bean = context.getBean(studentController.class);
           System.out.println(bean);
       }
   }
}

在这里插入图片描述



  • @Scope("prototype") 【每次都会创建一个新的实例】
@RestController
@Scope("prototype")
public class studentController {
    studentController(){
        System.out.println("构造器执行了~~~");
    }
}
@SpringBootTest
class SpringBootPrincipleApplicationTests {
    @Autowired
    private ApplicationContext context;

    @Test
   public void testScope(){
       for (int i = 0; i < 5; i++) {
           studentController bean = context.getBean(studentController.class);
           System.out.println(bean);
       }
   }
}

在这里插入图片描述



2.3 加载第三方bean

  • 现在我们的项目的pom.xml文件中引入解析XML文件的第三方bean:SAXReader

现在我们直接在测试类中获取SAXReader的bean对象

@SpringBootTest
class SpringBootPrincipleApplicationTests {
    @Autowired
    private ApplicationContext context;

    @Test
   public void testOtherBean() throws DocumentException {
        SAXReader bean = context.getBean(SAXReader.class);
        System.out.println(bean);
    }
}

在这里插入图片描述

结论:通过pom文件引入的第三方依赖,不能直接获取它的bean对象


下面是把第三方依赖的bean交给IOC容器管理的步骤

  1. 创建一个类,上面加上@Configuration注解,标记这个类为配置类
@Configuration
public class SAXReaderConfig {
    
}
  1. 在类中创建一个方法,并用@Bean注解修饰,这个方法的返回值是我们引入的第三方bean对象,方法的名字作为IOC中bean的名字
@Configuration
public class SAXReaderConfig {
    @Bean
    public SAXReader saxReader(){
        return new SAXReader();
    }
}
@SpringBootTest
class SpringBootPrincipleApplicationTests {
    @Autowired
    private ApplicationContext context;
    
    @Test
   public void testOtherBean() throws DocumentException {
        SAXReader bean = context.getBean(SAXReader.class);
        System.out.println(bean);
    }
}
  1. 补充:如果方法中需要用到其它bean,可以在方法的参数列表中直接注入
@Configuration
public class SAXReaderConfig {
    @Bean
    public SAXReader saxReader(studentController student){
        System.out.println(student);
        return new SAXReader();
    }
}



三、SpringBoot原理

3.1 依赖传递

依赖传递实际上就是如果一个模块依赖另一个模块,就会拥有这个模块以及这个模块的依赖。就比如我们开发web程序当中要引入很多相关的依赖,但通过SpringBoot的起步依赖,就是spring-boot-starter-web这个依赖,我们只需要引入这个依赖即可,因为spring-boot-starter-web这个依赖集成了所有web开发的常见依赖,这正是由于Maven的依赖传递

在这里插入图片描述



3.2 自动配置

SpringBoot项目除了自己使用注解将对象交给IOC容器进行管理,还有一部分对象是通过SpringBoot自动配置将其资源加入到IOC容器中

在这里插入图片描述



3.2.1 自动配置加载资源的方案

前置步骤

  1. 在工程中导入所要依赖的模块(必须是Springboot模块,因为要依赖spring的注解)

在这里插入图片描述

  1. 在主模块的pom.xml文件中导入依赖模块的坐标
        <!--第三方模块依赖-->
        <dependency>
            <groupId>com.itheima</groupId>
            <artifactId>TempModule</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>


  • 方案一

在主模块的启动类上加上@ComponentScan注解,并指定要扫描的包名字符串

注意:@ComponentScan这个注解只能扫描包中已经交由IOC容器管理的类

在这里插入图片描述


@SpringBootApplication
@ComponentScan({"com.example","com.itheima"})
public class SpringBootPrincipleApplication {

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

}

// 自动配置  方案一
@SpringBootTest
class SpringBootPrincipleApplicationTests {
    @Autowired
    private ApplicationContext context;

    @Test
    public void testTempModule(){
        TokenParse bean = context.getBean(TokenParse.class);
        System.out.println(bean);
    }
}

在这里插入图片描述



  • 方案二

在主模块的启动类加上@Import()注解,并指定类的class对象,使用此注解导入的类会被Spring加载到IOC容器(以下分别是启动类测试类)

  1. 导入普通类

在这里插入图片描述

// 导入普通类
@Import({HeaderParse.class})
@SpringBootApplication

public class SpringBootPrincipleApplication {

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

}
// 自动配置  方案二(导入普通类)
@SpringBootTest
class SpringBootPrincipleApplicationTests {
    @Autowired
    private ApplicationContext context;

    @Test
    public void testTempModule(){
        HeaderParse bean1 = context.getBean(HeaderParse.class);
        System.out.println(bean1);
    }
}


  1. 导入配置类

在这里插入图片描述

@Import(TempConfig.class)
@SpringBootApplication

public class SpringBootPrincipleApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootPrincipleApplication.class, args);
    }
}
// 自动配置  方案二(导入配置类)
@SpringBootTest
class SpringBootPrincipleApplicationTests {
    @Autowired
    private ApplicationContext context;

    @Test
    public void testTempModule(){
        HeaderParse bean1 = context.getBean(HeaderParse.class);
        System.out.println(bean1);
    }
}

  1. 导入ImportSelector的实现类
  • 实现ImportSelector接口时一定要重写selectImports方法

在这里插入图片描述

@Import(TempImportSelector.class)
@SpringBootApplication

public class SpringBootPrincipleApplication {

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

}
// 自动配置  方案二(导入ImportSelector实现类)
@SpringBootTest
class SpringBootPrincipleApplicationTests {
    @Autowired
    private ApplicationContext context;

    @Test
    public void testTempModule(){
        HeaderParse bean1 = context.getBean(HeaderParse.class);
        System.out.println(bean1);
    }
}

  1. 使用自定义注解包装@Import【推荐使用】

使用自定义注解包装@Import,自定义注解可以包装以上三种方式,下面举例说明其中一种即可

在这里插入图片描述

public class HeaderParse {
    public void parse(){
        System.out.println("HeaderParse....");
    }
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(HeaderParse.class)
public @interface temp {
}
@temp
@SpringBootApplication

public class SpringBootPrincipleApplication {

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

}
// 自动配置  方案二(自定义注解包装类)
@SpringBootTest
class SpringBootPrincipleApplicationTests {
    @Autowired
    private ApplicationContext context;

    @Test
    public void testTempModule(){
        HeaderParse bean1 = context.getBean(HeaderParse.class);
        System.out.println(bean1);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值