SpringBoot二:容器功能(和Spring相关)

容器功能

目的:
  1. 为了深入理解springboot的自动配置原理,需要先了解springboot的部分底层注解

  2. 容器功能相关的注解汇总

    注解名称功能
    1@Configuration标注该类为配置类
    2@Bean标注在方法上,通过方法添加组件,
    常用于导入第三包中的组件
    3@Compont添加普通组件
    4@Controller添加控制类组件
    5@Service添加业务层组件
    6@Repository添加持久层组件
    7@Import快速给容器中导入组件
一、组件添加
  1. 创建一个配置类 - @Configuration

    配合属性proxyBeanMethod使用

    /*
        @Configuration:表明该类是配置类
        ① 配置类本身也是一个组件
        ② proxyBeanMethod:默认值是true,表明配置类是一个代理对象
           Full配置模式:proxyBeanMethods = true,代理对象调用方法,springboot总会检查容器中是否有方法对应的组件,保持组件单实例,即外部无论获取多少次该组件,都是容器中的单实例
           Lite配置模式:proxyBeanMethods = false,表明配置类不是代理对象了,即,配置类再调用方法时,就只是单纯的调用方法,不会从容器中获取,每次都创建新的对象
        ③ 如果组件之间有依赖关系,proxyBeanMethods必须为true。
    
    */
    @Configuration(proxyBeanMethods = true)
    public class MyConfig {
        
    }
    
  2. 在配置类内以@Bean注解添加组件
    @Configuration(proxyBeanMethods = true)
    public class MyConfig {
        /*
            @Bean:标注在方法上给容器中添加组件。默认是单实例
            ① 方法名:作为组件的id,
            ② 返回类型:就是组件类型。
            ③ 返回的值:就是组件在容器中的实例。
        */
        @Bean
        public User user01() {
            User zhangsan = new User("zhangsan", 18);
            // 与tomcatPet()组件产生了依赖
            zhangsan.setPet(tomcatPet());
            return zhangsan;
        }
        @Bean
        public Pet tomcatPet() {
            return new Pet("tomcat");
        }
    }
    
  3. Spring5中的IOC容器中添加组件的注解也可以使用

    @Component、@Controller、@Service、@Repository

    参考博文:Spring5框架四:IOC操作 - 基于注解_e_nanxu的博客-CSDN博客

  4. @import(Class<?> [])

    写在容器中的任意一个的组件上,给容器中自动创建出引入的类的组件,引入的类可以是自建类,也可以是第三方jar包中的类。

    创建的组件名默认为该类的全类名

    @Import({User.class, DBNameResolver.class})
    @Configuration(proxyBeanMethods = true)
    public class MyConfig {
        
    }
    
  5. @Conditional()条件装配

    按照条件进行装配,即满足@Conditional或其派生注解中的条件,该组件才会被装进容器

    // 1.放在配置类上,如果不满足Conditional中的条件,则整个配置类中的所有组件都无法装入容器
    @ConditionalOnBean(name = "user01")
    @Configuration(proxyBeanMethods = true)
    public class MyConfig {
        @Bean
        public User user01() {
            User zhangsan = new User("zhangsan", 18);
            zhangsan.setPet(tomcatPet());
            return zhangsan;
        }
        @Bean
        public Pet tomcatPet() {
            return new Pet("tomcat");
        }
    }
    // 2.放在某个组件上,如果不满足Conditional中的条件,则这个组件无法装入容器
    @Configuration(proxyBeanMethods = true)
    public class MyConfig {
        @Bean
        public User user01() {
            User zhangsan = new User("zhangsan", 18);
            zhangsan.setPet(tomcatPet());
            return zhangsan;
        }
        @ConditionalOnBean(name = "user01")
        @Bean
        public Pet tomcatPet() {
            return new Pet("tomcat");
        }
    }
    
    @Conditional()的派生注解

    在这里插入图片描述

  6. @ImportResource原生配置文件导入

    在配置类上,使用该注解导入第三方或者原项目中的xml配置文件中的组件

    @ImportResource("classpath:beans.xml")
    @Configuration(proxyBeanMethods = true)
    public class MyConfig {
    
    }
    
二、配置绑定
  1. 配置文件:application.properties
    mycar.name=BYD
    mycar.price=100000
    
  2. 配置绑定
    方式一:@Component + @ConfigurationProperties

    在bean文件夹下创建一个对应的实体类组件

    / 只有在spring容器中的组件,才能拥有SpringBoot提供的强大功能
    @Component
    @ConfigurationProperties(prefix="mycar")
    public class Car {
        private String name;
        private Double price;
    
        // 此处省略了构造器、get/set方法及toString方法    
    }
    
    方式二:@ConfigurationProperties +@EnableConfigurationProperties
    @ConfigurationProperties(prefix="mycar")
    public class Car {
        private String name;
        private Double price;
        // 此处省略了构造器、get/set方法及toString方法    
    }
    
    // 开启了Car配置绑定功能,并将Car自动注册到了容器中
    @Configuration(proxyBeanMethods = true)
    @EnableConfigurationProperties(Car.class)
    public class MyConfig {
        
    }
    
  3. 业务组件
    @RestController
    public class HelloController {
        @Autowired
        Car car;
        @RequestMapping("mycar")
        public Car handler02() {
            return car;
        }
    }
    
三、自动扫描main程序所在包下的所有组件的源码解析
  1. 主程序类的注解@SpringBootApplication源码
    /* 主要包含三个注解
       ① @SpringBootConfiguration:和@Configuration作用一样,表明主程序类也是配置类
       ② @EnableAutoConfiguration:重点解析该注解源码
       ③ @ComponentScan:组件扫描
    */
    
    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @SpringBootConfiguration
    @EnableAutoConfiguration
    @ComponentScan(
        excludeFilters = {@Filter(
        type = FilterType.CUSTOM,
        classes = {TypeExcludeFilter.class}
    ), @Filter(
        type = FilterType.CUSTOM,
        classes = {AutoConfigurationExcludeFilter.class}
    )}
    )
    public @interface SpringBootApplication {
        // 省略内部程序
    }
    
  2. @EnableAutoConfiguration源码
    // @AutoConfigurationPackage:重点解析
    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @AutoConfigurationPackage
    @Import({AutoConfigurationImportSelector.class})
    public @interface EnableAutoConfiguration {
        String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
    
        Class<?>[] exclude() default {};
    
        String[] excludeName() default {};
    }
    
  3. @AutoConfigurationPackage源码
    // 重点解析Resistrar
    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @Import({Registrar.class})
    public @interface AutoConfigurationPackage {
        String[] basePackages() default {};
    
        Class<?>[] basePackageClasses() default {};
    }
    
  4. Registrar,内部静态类源码
    public abstract class AutoConfigurationPackages {    
    	static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
                Registrar() {
                }
    			// 在该方法上打断点进行De
                public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
                    AutoConfigurationPackages.register(registry, (String[])(new AutoConfigurationPackages.PackageImports(metadata)).getPackageNames().toArray(new String[0]));
                }
    
                public Set<Object> determineImports(AnnotationMetadata metadata) {
                    return Collections.singleton(new AutoConfigurationPackages.PackageImports(metadata));
                }
            }
    }
    
  5. 在registerBeanDefinitions方法上断点测试情况

    在这里插入图片描述

四、最佳实践
  1. 引入相关场景启动器

    在官方文档中可以查找有哪些场景启动器依赖或找某些第三方提供的场景启动器依赖

  2. 查看自动配置了哪些

    ① 手动查看,在External LIbiraries中的spring-boot-autoconfigure中

    ② 在配置文件中,配置debug=true,启动自动配置报告,执行主程序即可获得所有自动装配的情况,

    ​ 其中生效的为Positive,未生效的为Negative

  3. 是否需要修改properties

    可在官方文档中查看:Common Application Properties (spring.io)

  4. 自定义

    可以自定义加入或替换组件

    自定义器 xxxxCustomizer(高级特性,后续学习)

  5. 更改组件扫描路径
    @SpringBootApplication(scanBasePackages = "com.atg")
    
小结
  1. spring主要功能之一,就是将各类的对象以组件的形式装入到IOC容器中。
  2. springboot中的@bean标注的方法内创建的对象就是xml配置中bean标签的
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

e_nanxu

感恩每一份鼓励-相逢何必曾相识

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值