155_SpringBoot_自动装配

举报
alexsully 发表于 2021/09/18 17:30:50 2021/09/18
【摘要】 SpringBoot是整合Spring技术栈的一站式框架SpringBoot是简化Spring技术栈的快速开发脚手架1 SpringBoot特点1.1 依赖管理a) 父项目做依赖管理 <!-- 父依赖 几乎声明了所有开发中常用的依赖的版本号,自动版本仲裁机制--> <parent> <groupId>org.springframework.boot</groupId>...

SpringBoot是整合Spring技术栈的一站式框架
SpringBoot是简化Spring技术栈的快速开发脚手架

1 SpringBoot特点

1.1 依赖管理

a) 父项目做依赖管理

  <!-- 父依赖  几乎声明了所有开发中常用的依赖的版本号,自动版本仲裁机制-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.4</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

b) 开发导入starter场景启动器
c) 无需关注版本号,自动版本仲裁

        <!-- web场景启动器 -->
<!--        1、见到很多 spring-boot-starter-* : *就某种场景-->
<!--        2、只要引入starter,这个场景的所有需要的依赖我们都自动引入-->
<!--        3、所有场景启动器最底层的依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

d) 可以修改默认版本号

    <mysql.version>8.0.26</mysql.version>
	1 查看spring-boot-dependencies里面规定当前依赖的版本 用的key。
    2 在当前项目里面重写配置
    <properties>
        <mysql.version>5.1.43</mysql.version>
    </properties>

1.2 自动配置

 a)自动配好SpringMVC -引入SpringMVC全套组件
    自动配好SpringMVC常用组件(功能)
    自动配好Web常见功能,如:字符编码问题
 b) SpringBoot帮我们配置好了所有web开发的常见场景
 c)默认的包结构
    主程序所在包及其下面的所有子包里面的组件都会被默认扫描进来
    无需以前的包扫描配置
    想要改变扫描路径,@SpringBootApplication(scanBasePackages="com.alex") 或者@ComponentScan 指定扫描路径

@SpringBootApplication
等同于
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan("com.atguigu.alex")

@SpringBootApplication
public class SpringbootDemo1Application {

    public static void main(String[] args) {
//        SpringApplication.run(SpringbootDemo1Application.class, args);
        // 1 返回 IOC 容器
        ConfigurableApplicationContext run = SpringApplication.run(SpringbootDemo1Application.class, args);
        //2、查看容器里面的组件
        String[] names = run.getBeanDefinitionNames();
//        for (String name : names) {
//            System.out.println(name);
//        }
}


2 容器功能_组件添加

a) @Configuration @ComponentScan
Full模式与Lite模式
Lite模式:配置类组件之间无依赖关系,加速容器启动过程,减少判断
Full模式: 配置类组件之间有依赖关系,方法会被调用得到之前单实例组件

b) @import  &  @ImportResource

c) @Conditional 条件装配:满足Conditional指定的条件,则进行组件注入


d) 配置绑定 

 @ConfigurationProperties
    @EnableConfigurationProperties + @ConfigurationProperties
    @Component + @ConfigurationProperties

pojo类

@Component
@Data
@AllArgsConstructor
@NoArgsConstructor
//@ConfigurationProperties(prefix = "dog")
public class Dog {
    private String name;
    private  int age;
}

@Data
@AllArgsConstructor
@NoArgsConstructor
@Component
public class Car {
    private String brand;
    private Integer price;
}


beans.xml

<?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="dog" class="com.alex.pojo.Dog">
        <property name="name" value="B哥"/>
        <property name="age" value="20"/>
    </bean>

</beans>


Myconfig 类

/**
 * proxyBeanMethods:代理bean的方法  组件依赖必须使用Full模式默认。其他默认是否Lite模式
 *   Full(proxyBeanMethods = true)、【保证每个@Bean方法被调用多少次返回的组件都是单实例的】
 *   Lite(proxyBeanMethods = false)【每个@Bean方法被调用多少次返回的组件都是新创建的】
 *      @Import({User.class, DBHelper.class})
 *        给容器中自动创建出这两个类型的组件、默认组件的名字就是全类名
 *      @ImportResource("classpath:beans.xml")导入Spring的配置文件,
 */

@EnableConfigurationProperties(Car.class)  //1 开启Car配置绑定功能 //2 把这个Car这个组件自动注册到容器中
@ConditionalOnMissingBean(name = "bob")
@ImportResource("classpath:beans.xml")
@Import(Dog.class)
@Configuration(proxyBeanMethods = true)    //告诉SpringBoot这是一个配置类 == 配置文件
public class MyConfig {
    @Autowired
    Car car;


    @Bean("jiefu") //给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。返回的值,就是组件在容器中的实例
    public Dog getDog(){
        return new Dog("jiefu", 30);
    }
}


@SpringBootApplication
public class SpringbootDemo1Application {

    public static void main(String[] args) {
//        SpringApplication.run(SpringbootDemo1Application.class, args);
        // 1 返回 IOC 容器
        ConfigurableApplicationContext run = SpringApplication.run(SpringbootDemo1Application.class, args);
        //2、查看容器里面的组件
        String[] names = run.getBeanDefinitionNames();
//        for (String name : names) {
//            System.out.println(name);
//        }

        Dog d1 = run.getBean("jiefu", Dog.class);

        MyConfig bean = run.getBean(MyConfig.class);
        Dog d2 = bean.getDog();
        System.out.println(d1 == d2 );  // true  false

        System.out.println("----");
        String[] dog_class = run.getBeanNamesForType(Dog.class);
        for (String s : dog_class) {
            System.out.println(s);// dog (import进来的 ,默认是类名小写)   jiefu(@bean 注解进来的)
        }

    }
}


3 自动配置原理

 1 引导加载自动配置类

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


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

2 @ComponentScan 指定扫描哪些,Spring注解

3 @EnableAutoConfiguration

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

a) @AutoConfigurationPackage 自动配置包 指定了默认的包规则

    @Import(AutoConfigurationPackages.Registrar.class)  //给容器中导入一个组件
public @interface AutoConfigurationPackage {}

//利用Registrar给容器中导入一系列组件
//将指定的一个包下的所有组件导入进来?MainApplication 所在包下。

b) @Import(AutoConfigurationImportSelector.class)

1、利用getAutoConfigurationEntry(annotationMetadata);给容器中批量导入一些组件
2、调用List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes)获取到所有需要导入到容器中的配置类
3、利用工厂加载 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 

4 按需开启自动配置项

    虽然我们127个场景的所有自动配置启动的时候默认全部加载。xxxxAutoConfiguration
    按照条件装配规则(@Conditional),最终会按需配置。

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

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


总结:

SpringBoot先加载所有的自动配置类  xxxxxAutoConfiguration
每个自动配置类按照条件进行生效,默认都会绑定配置文件指定的值。xxxxProperties里面拿。xxxProperties和配置文件进行了绑定
生效的配置类就会给容器中装配很多组件
只要容器中有这些组件,相当于这些功能就有了
定制化配置
用户直接自己@Bean替换底层的组件
用户去看这个组件是获取的配置文件什么值就去修改。
xxxxxAutoConfiguration ---> 组件  ---> xxxxProperties里面拿值  ----> application.properties
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。