SpringBoot框架原理

SpringBoot框架原理

1.配置优先级
  • SpringBoot底层支持三种配置文件:application.properties、application.yml、application.yaml

  • 一个项目中如果三种配置文件配置了相同的内容,优先级是properties>yml>yaml,yml是主流

  • SpringBoot为了增强程序的扩展性,除了支持配置文件方式以外,还支持两种常见的配置方式

    Java系统属性配置(格式:-Dkey=value)

    命令行参数(格式:–key=value)

    一般情况下使用方式在不影响源代码修改的时候额外给出

    优先级:命令行参数>系统属性参数>properties参数>yml参数>yaml参数

  • 当已经有了一个可以运行的jar包想要临时修改配置进行启动的时候,可以使用命令行参数与Java系统属性

    例:java -jar chapter-15-01-spring-boot-configuration-0.0.1-SNAPSHOT.jar --server.port=10086

    java -Dserver.port=10099 -jar chapter-15-01-spring-boot-configuration-0.0.1-SNAPSHOT.jar

2.Bean管理

(1)获取Bean

  • 从容器中获取Bean需要基于容器对象完成,容器对象可以基于DI的方式进行注入

    @Resource
    private ApplicationContext applicationContext;
    
  • 三种获取方式

    基于容器名称

    注入Bean到容器中没有手动声明名称的情况下默认名称就是小驼峰形式

    @Test
    public void getBeanByName() {
        DeptController deptController = (DeptController) applicationContext.getBean("deptController");
        log.info("基于容器中名称从容器中获取的Bean是 : {}", deptController);
    }
    

    基于容器中类型

    @Test
    public void getBeanByType() {
        //基于指定类型从容器中获取Bean
        IDeptService iDeptService = applicationContext.getBean(IDeptService.class);
        log.info("基于容器中类型从容器中获取的Bean是 : {}", iDeptService);
    }
    

    基于容器中名称+类型

    @Test
    public void getBeanByNameAndType() {
        EmpMapper empMapper = applicationContext.getBean("empMapper", EmpMapper.class);
        log.info("基于容器中类型与名称获取到的Bean是 : {}", empMapper);
        //org.apache.ibatis.binding.MapperProxy@192f5f39
    }
    

使用三种方式获取一个Bean对象,对象的地址值是一样的,说明默认情况下IOC容器中Bean对象是单例

(2)Bean的作用域

  • 单例饿汉式加载

    @Component //将该类对象交给Spring管理(@Scope:单例)
    public class A(){}
    

    容器中只会存在一个该类对象,会在项目启动的时候进行创建并放到容器中

  • 单例懒汉式加载

    @Lazy
    @Component //将该类交给Spring管理,只有在第一次获取的时候才会创建该类对象
    public class B{}
    

    前提:当一个类构成比较复杂并且使用频率不高

    默认Singleton的Bean,在容器启动时被创建,可以使用 @Lazy注解来延迟初始化(延迟到第一次使用时)

  • 多例懒汉式加载

    @Scope("prototype")
    @Component //将该类交给Spring管理,每次尝试获取创建一个新的对象
    public class C{}
    

    容器会在每次获取该类对象的时候进行创建并放到容器中

  • 5种作用域

    singleton:容器内同名称的bean只有一个实例(单例)默认的

    prototype:每次使用该bean时会创建新的实例,非单例,是多例

    request:每个请求范围内会创建新的实例(web环境中)

    session:每个绘画范围内会创建新的实例(web环境中)

    application:每个应用范围内会创建新的实例(web环境中)

(3)第三方Bean

第三方Bean指的是依赖包中的类加载到IOC容器中

有三种情况:

  • 使用者主动加载
  • 使用者与开发者配合加载
  • 开发者自动装配加载

主动加载的解决方案

  • 引入Dom4j依赖核心类SaxReader注入到IOC容器中

    
    <dependency>
        <groupId>org.dom4jgroupId>
        <artifactId>dom4jartifactId>
        <version>2.1.3version>
    dependency>
    
  • 明确要加载的Bean的类型SaxReader

  • 编写一个配置类标记@Configuration注解,目的是让Spring扫描该类

  • 在配置类中编写一个方法,将要加载的Bean的类型作为方法的返回值声明,方法名称就是Bean在容器中的名称

    @Configuration //当Spring扫描到该类的时候会明确该类是一个配置类(继续在类中扫描剩余内容)
    public class BeanConfiguration {
        @Bean
        public SAXReader saxReader() {
            return new SAXReader(); //将返回值作为对象注入到IOC容器
        }
    }
    
  • 方法声明完成后需要标记@Bean注解

当Spring扫描到配置类的时候会继续扫描类中的@Bean标记的方法将返回值放到IOC容器中,容器中Bean的名称默认就是方法的名称

当被@Bean标记的方法在执行的过程中需要其他Bean才可以完成构建,直接在方法的形参上声明即可,Spring会自动在执行该方法的时候去容器中找满足形参类型的Bean注入,如果没有就报错

@Bean
public SAXReader saxReader(A a) {
    log.info("在构建SaxReader的过程中参数a的内容是 : {}", a);
    return new SAXReader(); //将返回值作为对象注入到IOC容器
}
3.SpringBoot原理

(1)SpringBoot不是一个框架,而是简化了Spring核心框架的技术,但底层依然是Spring核心框架

(2)SpringBoot之所以可以让开发者更简单开发一个web程序底层有两大核心支撑:起步依赖和自动装配

(3)起步依赖类别

  • 官方的起步依赖:spring-boot-starter-技术集
  • 第三方技术提供的起步依赖:技术集-spring-boot-starter
  • 底层的技术支持:Maven的依赖传递,项目依赖a,a依赖b,相当于项目依赖b

(4)SpringBoot的自动装配就是当Spring容器启动之后,一些配置类、bean对象就自动存入IOC容器中,不需要手动去声明

(5)常见方案

  • @ComponentScan组件扫描

    @SpringBootApplication
    @ComponentScan({"com.itheima","com.example"}) //指定要扫描的包
    public class SpringbootWebConfig2Application {
        public static void main(String[] args) {
            SpringApplication.run(SpringbootWebConfig2Application.class, args);
        }
    }
    
  • @Import导入,使用@Import导入的类会被Spring加载到IOC容器中

    普通类

    基于@Import注解将需要注入到IOC容器中的第三方类的class对象作为参数传递

    @Import({Car.class, Machine.class})
    @SpringBootApplication
    public class Chapter1502SpringBootThirdBeanApplication { }
    

    好处和弊端

    好处:注入第三方Bean更方便

    弊端:1.基于无参来做,如果第三方Bean在创建的过程中需要其他的数据则无法操作

    ​ 2.使用者还是主动加载

    配置类

    依赖的提供者编写一个配置类,将所有要注入到容器中的第三方Bean在配置类中进行声明

    @Configuration 
    public class ThirdBeanConfiguration {
        @Bean
        public Car car() {
            return new Car();
        }
        @Bean
        public Machine machine() {
            return new Machine();
        }
    }
    

    使用者在使用的时候只需要通过@Import注解将第三方提供的配置类作为参数传递即可

    @Import(ThirdBeanConfiguration.class)
    @SpringBootApplication
    public class Chapter1502SpringBootThirdBeanApplication { }
    

    好处与弊端

    好处:注入第三方Bean更方便

    弊端:1.虽然依赖的编写者提供了配置类,但可能使用者并不知道有配置类

    ​ 2.这种方式就不是使用者一个人去导入,而是使用者和依赖编写者共同完成

    ImportSelector接口实现类

    ImportSelector是一个接口。接口就是规范,用于声明哪些Bean注入到宿主IOC容器中的规范,一般来说由依赖提供者实现该规范

    public class MyImportSelector implements ImportSelector {
        //作为依赖的提供者,实现该接口的目的就是声明哪些Bean需要注入到宿主容器中。
        //方法的返回值就是要注入到IOC容器中的Bean的全类名
        @Override
        public String[] selectImports(AnnotationMetadata importingClassMetadata) {
            System.out.println("开始返回要注入到宿主容器中的Bean的全类名数组!");
            //return new String[]{"com.example.entity.Car", "com.example.entity.Machine"};
            return new String[]{"com.example.configuration.ThirdBeanConfiguration"};
        }
    }
    

    使用者在使用的时候只需要通过@Import注解将第三方提供好的ImportSelector实现类作为参数传递即可

    @Import(MyImportSelector.class)
    @SpringBootApplication
    public class Chapter1502SpringBootThirdBeanApplication { }
    

    Spring会自动将实现类中selectImports方法返回的数组中的每一个类再进行扫描完成注入

    好处与弊端

    好处:1.注入第三方Bean更方便

    ​ 2.依赖的提供者可以先编写多个Configuration配置类,再将多个configuration配置类的全类名整 合在一起

    弊端:这种方式使用者和编写者要共同完成

    注解

    依赖的提供者编写一个注解,在注解上开启只能够标记在类上/存活到运行期/@Import注解引入要注入的Bean/配置类

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Import(MyImportSelector.class)
    public @interface EnableThirdBeanImport {
        
    }
    

    使用者只需要将注解标记在核心类上,后续Spring会继续扫描注解中的相关内容

    @EnableThirdBeanImport
    @SpringBootApplication
    public class Chapter1502SpringBootThirdBeanApplication { }
    

    SpringBoot自动装配原理:SpringBoot项目的启动类上有一个@SpringBootConfiguration注解,进入源码,该注解上使用了一个@EnableAutoConfiguration核心注解,使用@Import注解导入了ImportSelector接口的实现类,加载该配置类,获取所有META-INF/spring.factories的文件,该文件中存储的都是以EnableAutoConfiguration为键,以及该键对应的值的map集合,键唯一,值有多个。配置类中有很@Bean标注的方法,这些方法不全都加载到IOC容器中,可通过@Conditional的衍生注解,在满足某些前提下,注入到IOC容器中

你可能感兴趣的:(spring,boot,后端,java)