SpringBoot2-[SpringBoot自动装配、容器功能]

简介: SpringBoot2-[SpringBoot自动装配、容器功能]

在这里插入图片描述

👨🏻‍🎓博主介绍:大家好,我是芝士味的椒盐,一名在校大学生,热爱分享知识,很高兴在这里认识大家🌟
🌈擅长领域:Java、大数据、运维、电子
🙏🏻如果本文章各位小伙伴们有帮助的话,🍭关注+👍🏻点赞+🗣评论+📦收藏,相应的有空了我也会回访,互助!!!

🤝另本人水平有限,旨在创作简单易懂的文章,在文章描述时如有错,恳请各位大佬指正,在此感谢!!!

@[TOC]

SpringBoot自动装配

  • 主类使用了@SpringBootApplication,其内部的@EnableAutoConfiguration就会作用,开启自动装配

      # Initializers
      org.springframework.context.ApplicationContextInitializer=\
      org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
      org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener
    
      # Application Listeners
      org.springframework.context.ApplicationListener=\
      org.springframework.boot.autoconfigure.BackgroundPreinitializer
    
      # Auto Configuration Import Listeners
      org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\
      org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener
    
      # Auto Configuration Import Filters
      org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
      org.springframework.boot.autoconfigure.condition.OnBeanCondition,\
      org.springframework.boot.autoconfigure.condition.OnClassCondition,\
      org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition
                                                                                                  ......
    
  • 按需加载,只有导入了相关的依赖之后才会生效

  • 包扫描

    • 默认是扫描引导类(主类)的包所在的包及其子包下的Bean。
    • 各种配置拥有默认值
      • 默认配置最终都是映射到某个类上,如:MultipartProperties
      • 配置文件的值最终会绑定每个类上,这个类会在容器中创建对象
    • 也可以更改包扫描位置使用如下

        @SpringBootApplication(scanBasePackages = "icu.lookyousmileface.springboot_gettingstarted.controller")
      
    • 还可以不使用@SpringApplication注解,使用@ComponentScan注解,不可以和@SpringApplication注解一起用

        @SpringBootConfiguration
        @EnableAutoConfiguration
        @ComponentScan("icu.lookyousmileface.springboot_gettingstarted")
      
      • 会冲突

          @ComponentScan(
              excludeFilters = {
                 @Filter(
              type = FilterType.CUSTOM,
              classes = {
                 TypeExcludeFilter.class}
          ),
        

SpringBoot容器功能

  • @Configuration

    • Full模式与Lite模式

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

        @Configuration(proxyBeanMethods = true)
        public class MyConfig {
                 
        
          @Bean
          public Human human(){
                 
              return new Human("松江",18,'男');
          }
        
          public Pet pet(){
                 
              return new Pet("小黑","白色");
          }
        }
        
        public static void main(String[] args) {
                 
              ConfigurableApplicationContext run = SpringApplication.run(SpringbootGettingstartedApplication.class);
              //查看场景启动器带来的组件
              String[] beanDefinitionNames = run.getBeanDefinitionNames();
              Arrays.stream(beanDefinitionNames).forEach(S->System.out.println(S));
              //从容器获得对象
              Human human1 = run.getBean("human",Human.class);
              Human human2 = run.getBean("human",Human.class);
              System.out.println(human1==human2);
              //icu.lookyousmileface.springboot_gettingstarted.config.MyConfig$$EnhancerBySpringCGLIB$$21ae3889@15515c51 表示被代理
              MyConfig myConfig = run.getBean(MyConfig.class);
              System.out.println(myConfig);
              //config的proxyBeanMethods = true为单实列,否则每次调用都会产生一个新的对象
              Human human = myConfig.human();
              Human human3 = myConfig.human();
              System.out.println(human3==human);
        }
        
      • config类配置代替了大量的xml配置

  • @Bean(表示对象组件)、@Component(表示组件)、@Controller(表示控制器组件)、@Service(表示业务层组件)、@Repository(标注表示数据库组件)
  • @ComponentScan(包扫描)、@Import(导入组件)

    • @Import:使用@Import导入组件,其名字为全类名如:Human,@Bean注册的注册的类为首字母小写形势human

        */
        //使用@Import导入组件,其名字为全类名如:Human,@Bean注册的注册的类为首字母小写形势human
        @Import({
             Human.class,Pet.class})
        @Configuration(proxyBeanMethods = true)
        public class MyConfig {
             
      
            @Bean
            public Human human(){
             
                return new Human("松江",18,'男');
            }
      
            public Pet pet(){
             
                return new Pet("小黑","白色");
            }
        }
      
  • @Conditional

    • 条件装配:满足Conditional指定的条件,则进行组件注入,其下由多个子类如下:

      在这里插入图片描述

    • 代码实验:

        @Configuration
        public class MyConfig {
             
      
            @ConditionalOnMissingBean(name = "peto1")
            @Bean
            public Human human01(){
             
                return new Human("宋江",46,'男');
            }
      
        //    @Bean
            public Pet Peto1(){
             
                return new Pet("小黄","yellow");
            }
        }
      
      • @ConditionalOnMissingBean(name = "peto1")也就是说,如果没有"pet01"Bean这个名称的容器就创建human01,否则就将不创建Human类的对象, 可以作用在方法和类上。
  • @ImportResource(引入原生的配置文件), 例如:要倒入Spring原生bean配置文件如下

      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:context="http://www.springframework.org/schema/context"
             xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    
          <bean id="hu01" class="icu.lookyousmileface.springboot_gettinggide.bean.Human">
              <property name="name" value="武松"></property>
              <property name="age" value="19"></property>
              <property name="sex" value="男"></property>
          </bean>
    
          <bean id="pe01" class="icu.lookyousmileface.springboot_gettinggide.bean.Pet">
              <property name="name" value="cat"></property>
              <property name="color" value="red"></property>
          </bean>
      </beans>
    
    • 就可以在配置类上加上该注解如下,bean此时在resources目录下:

        @Configuration
        @ImportResource("classpath:bean.xml")
        public class MyConfig {
             
      
        //    @ConditionalOnMissingBean(name = "peto1")
            @Bean
            public Human human01(){
             
                return new Human("宋江",46,'男');
            }
      
            @Bean
            public Pet Peto1(){
             
                return new Pet("小黄","yellow");
            }
        }
      
  • 配置绑定(@ConfigurationProperties+@Component标注在要绑定属性的类上)

    • application.yml(选用的是yml,选用properties遇到中文会出现乱码)

        myhuman:
          name: 宋江
          age: 89
          sex:
    • Human.java

        @Component
        prefix表示和配置文件的前缀相同的属性开始匹配,也就是上述application.yml中的myhuman
        @ConfigurationProperties(prefix = "myhuman")
        public class Human {
             
            private String name;
            private int age;
            private String sex;
        }
      
      • ⚠️注意配置绑定之前需要导入配置出绑定处理器,解决没有提示的问题

          <!--配置文件处理器,properties参数绑定对象-->
            <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
          </dependency>
        
      • ⚠️为了减少不必要插件编译进jar包或war包,可进行排除

          <build>
                  <plugins>
                      <plugin>
                          <groupId>org.springframework.boot</groupId>
                          <artifactId>spring-boot-maven-plugin</artifactId>
                          <!--编译时排除不必要的类-->
                          <configuration>
                              <excludes>
                                  <exclude>
                                      <groupId>org.projectlombok</groupId>
                                      <artifactId>lombok</artifactId>
                                  </exclude>
                                  <exclude>
                                      <groupId>org.springframework.boot</groupId>
                                      <artifactId>spring-boot-configuration-processor</artifactId>
                                  </exclude>
                              </excludes>
                          </configuration>
                      </plugin>
                  </plugins>
              </build>
        
- [application.yml]
- Human.java

    ```java
    @AllArgsConstructor
    @NoArgsConstructor
    @Data
    @Accessors(chain = true)
    @EqualsAndHashCode
    //@Component
    @ConfigurationProperties(prefix = "myhuman")
    public class Human {
        private String name;
        private int age;
        private String sex;
    }
    ```

- MyConfig.java

    ```java
    @Configuration
    //@ImportResource("classpath:bean.xml")
    @EnableConfigurationProperties(Human.class)
    public class MyConfig {

    //    @ConditionalOnMissingBean(name = "peto1")
    //    @Bean
    //    public Human human01(){
    //        return new Human("宋江",46,"男");
    //    }

        @Bean
        public Pet Peto1(){
            return new Pet("小黄","yellow");
        }
    }
    ```

    - @EnableConfigurationProperties(Human.class):表示支持某个类参数绑定,也就是开启配置绑定功能,将Human这个组件注册到容器。注意不要存在其他注册该容器的情况否则报错。
  • 自动配置原理

    • @SpringBootConfiguration:@Configuration是一个配置类
    • @ComponentScan:包扫描
    • @EnableAutoConfiguration:自动装配核心

        @AutoConfigurationPackage
        @Import({
             AutoConfigurationImportSelector.class})
      
      1. @AutoConfigurationPackage

         @Import(AutoConfigurationPackages.Registrar.class)  //给容器中导入一个组件
         public @interface AutoConfigurationPackage {
                 }
        
         //利用Registrar给容器中导入一系列组件
         //将指定的一个包下的所有组件导入进来?MainApplication 所在包下。
        
      2. @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
        

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

    • 按需开启自动配置项

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

                        @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默认会在底层配好所有的组件。但是如果用户自己配置了以用户的优先

                  @Bean
              @ConditionalOnMissingBean
              public CharacterEncodingFilter characterEncodingFilter() {
                 
              }
        
    • 总结:

        • SpringBoot先加载所有的自动配置类  xxxxxAutoConfiguration
        • 每个自动配置类按照条件进行生效,默认都会绑定配置文件指定的值。xxxxProperties里面拿。xxxProperties和配置文件进行了绑定
        • 生效的配置类就会给容器中装配很多组件
        • 只要容器中有这些组件,相当于这些功能就有了
        • 定制化配置
        • 用户直接自己@Bean替换底层的组件
        • 用户去看这个组件是获取的配置文件什么值就去修改。
        xxxxxAutoConfiguration ---> 组件  ---> xxxxProperties里面拿值  ----> application.properties
      
    • 最佳实践

        • 引入场景依赖
            • https://docs.spring.io/spring-boot/docs/current/reference/html/using-spring-boot.html#using-boot-starter
        • 查看自动配置了哪些(选做)
            • 自己分析,引入场景对应的自动配置一般都生效了
            • 配置文件中debug=true开启自动配置报告。Negative(不生效)\Positive(生效)
        • 是否需要修改
            • 参照文档修改配置项
                • https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html#common-application-properties
                • 自己分析。xxxxProperties绑定了配置文件的哪些。
            • 自定义加入或者替换组件
                • @Bean@Component。。。
            • 自定义器  XXXXXCustomizer;
            • ......
      
  • 开发小技巧

    • lombok:通过注解的方式创建get/set/toString等方法,提高编写bean的效率,也可以使用Slfj日志输出。
    • devtools:跟JRebel差不多的热部署工具,只要倒入其依赖即可使用,快捷键Control+F9

        <!--springboot的热部署工具-->
        <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-devtools</artifactId>
                    <version>2.0.4.RELEASE</version>
        </dependency>
      
相关文章
|
4月前
|
XML Java 应用服务中间件
【SpringBoot(一)】Spring的认知、容器功能讲解与自动装配原理的入门,带你熟悉Springboot中基本的注解使用
SpringBoot专栏开篇第一章,讲述认识SpringBoot、Bean容器功能的讲解、自动装配原理的入门,还有其他常用的Springboot注解!如果想要了解SpringBoot,那么就进来看看吧!
565 2
|
7月前
|
缓存 前端开发 Java
SpringBoot 实现动态菜单功能完整指南
本文介绍了一个动态菜单系统的实现方案,涵盖数据库设计、SpringBoot后端实现、Vue前端展示及权限控制等内容,适用于中后台系统的权限管理。
758 1
|
9月前
|
安全 Java API
Spring Boot 功能模块全解析:构建现代Java应用的技术图谱
Spring Boot不是一个单一的工具,而是一个由众多功能模块组成的生态系统。这些模块可以根据应用需求灵活组合,构建从简单的REST API到复杂的微服务系统,再到现代的AI驱动应用。
1184 8
|
8月前
|
监控 安全 Java
Java 开发中基于 Spring Boot 3.2 框架集成 MQTT 5.0 协议实现消息推送与订阅功能的技术方案解析
本文介绍基于Spring Boot 3.2集成MQTT 5.0的消息推送与订阅技术方案,涵盖核心技术栈选型(Spring Boot、Eclipse Paho、HiveMQ)、项目搭建与配置、消息发布与订阅服务实现,以及在智能家居控制系统中的应用实例。同时,详细探讨了安全增强(TLS/SSL)、性能优化(异步处理与背压控制)、测试监控及生产环境部署方案,为构建高可用、高性能的消息通信系统提供全面指导。附资源下载链接:[https://pan.quark.cn/s/14fcf913bae6](https://pan.quark.cn/s/14fcf913bae6)。
1711 0
|
10月前
|
SQL 前端开发 Java
深入理解 Spring Boot 项目中的分页与排序功能
本文深入讲解了在Spring Boot项目中实现分页与排序功能的完整流程。通过实际案例,从Service层接口设计到Mapper层SQL动态生成,再到Controller层参数传递及前端页面交互,逐一剖析每个环节的核心逻辑与实现细节。重点包括分页计算、排序参数校验、动态SQL处理以及前后端联动,确保数据展示高效且安全。适合希望掌握分页排序实现原理的开发者参考学习。
677 4
|
前端开发 JavaScript Java
SpringBoot实现国际化i18n功能
SpringBoot实现国际化i18n功能
1333 0
SpringBoot实现国际化i18n功能
|
4月前
|
JavaScript Java 关系型数据库
基于springboot的项目管理系统
本文探讨项目管理系统在现代企业中的应用与实现,分析其研究背景、意义及现状,阐述基于SSM、Java、MySQL和Vue等技术构建系统的关键方法,展现其在提升管理效率、协同水平与风险管控方面的价值。
|
4月前
|
搜索推荐 JavaScript Java
基于springboot的儿童家长教育能力提升学习系统
本系统聚焦儿童家长教育能力提升,针对家庭教育中理念混乱、时间不足、个性化服务缺失等问题,构建科学、系统、个性化的在线学习平台。融合Spring Boot、Vue等先进技术,整合优质教育资源,提供高效便捷的学习路径,助力家长掌握科学育儿方法,促进儿童全面健康发展,推动家庭和谐与社会进步。