zoukankan      html  css  js  c++  java
  • 【SpringBoot2 从0开始】底层注解

    一、配置类

    @Configuration这个注解作用就是告诉 springboot 这是一个配置类。

    这个配置已经不陌生了,在之前 spring 相关的使用全注解方式时,就使用到了配置类。

    在配置类里,可以使用@Bean标记在方法上,给容器注册组件,默认也是单实例的。

    @Configuration //告诉SpringBoot这是一个配置类 == 配置文件
    public class MyConfig {
    
        @Bean("user1") //给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。返回的值,就是组件在容器中的实例
        public User user01(){
            return new User("pingguo", 20);
        }
    
        @Bean("pet1")
        public Pet tomcatPet(){
            return new Pet("tomcat");
        }
    }
    

    主运行类还是之前示例中的,打印出所有组件的名称。

    可以看到,有上面注册的 2 个组件:user1、pet1

    二、配置类本身也是组件

    在主运行类的 main 方法里,加一个获取配置类的输出:

    @SpringBootApplication(scanBasePackages = "com.pingguo")
    public class MainApplication {
        public static void main(String[] args) {
            // 返回IOC容器
            final ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
    
            // 查看容器里的组件
            final String[] beanDefinitionNames = run.getBeanDefinitionNames();
    
            for (String name: beanDefinitionNames) {
                System.out.println(name);
            }
    
            // 从容器中获取组件
            MyConfig bean = run.getBean(MyConfig.class);
            System.out.println("配置类也是组件:" + bean);
        }
    }
    

    运行 main 方法,

    可以看到最后一个输出,说明配置类本身也是个组件。

    三、proxyBeanMethods 属性

    springboot2.0之后,@Configuration 中多了一个属性 proxyBeanMethods,用来代理 bean 的。

    默认值是true,也就是说该配置类会被代理(CGLIB),在同一个配置文件中调用其它被@Bean注解标注的方法获取对象时,springboot 总会检查容器中是否存在这个组件。

    如果容器中存在,直接取。不存在的话,才会去创建,保证单实例。

    现在看下false的情况。

    @Configuration(proxyBeanMethods = false) //改成 false
    public class MyConfig {
    
        @Bean("user1") //给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。返回的值,就是组件在容器中的实例
        public User user01(){
            return new User("pingguo", 20);
        }
    
        @Bean("pet1")
        public Pet tomcatPet(){
            return new Pet("tomcat");
        }
    }
    

    在主运行程序里多从调用方法获取对象,判断一下对象是否相等。

    @SpringBootApplication(scanBasePackages = "com.pingguo")
    public class MainApplication {
        public static void main(String[] args) {
            // 返回IOC容器
            final ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
    
            // 查看容器里的组件
            final String[] beanDefinitionNames = run.getBeanDefinitionNames();
    
            for (String name: beanDefinitionNames) {
                System.out.println(name);
            }
    
            // 从容器中获取组件
            MyConfig bean = run.getBean(MyConfig.class);
            System.out.println("配置类也是组件:" + bean);
    
            User user1 = bean.user01();
            User user2 = bean.user01();
            System.out.println(user1 == user2);
        }
    }
    

    看最后的输出,会是 false。

    这里引出 2 个名词:Full 全模式Lite 轻量级模式

    • Full (proxyBeanMethods = true) : 该模式下注入容器中的同一个组件无论被取出多少次都是同一个bean实例,即单实例对象,
      在该模式下 SpringBoot 每次启动都会判断检查容器中是否存在该组件。

    • Lite (proxyBeanMethods = false): 该模式下注入容器中的同一个组件无论被取出多少次都是不同的bean实例,即多实例对象,
      在该模式下 SpringBoot 每次启动会跳过检查容器中是否存在该组件。

    那么这个是用来解决什么场景的问题呢?答案:组件依赖

    有组件依赖的场景

    看下2个实体类:User、Pet。

    public class User {
        private String name;
        private Integer age;
        private Pet pet;
    ... ...
    

    固定代码部分:有参构造、无参构造、get和set方法、toString方法,就省去了。

    public class Pet {
        private String name;
    ... ...
    

    修改下配置类里的方法:

    @Configuration(proxyBeanMethods = true)
    public class MyConfig {
    
        @Bean("user1") 
        public User user01(){
            User pingguo = new User("pingguo",20);
            pingguo.setPet(tomcatPet());
            return pingguo;
        }
    
        @Bean("pet1")
        public Pet tomcatPet(){
            return new Pet("tomcat");
        }
    }
    

    到main方法测试一下:

        // 依赖关系
        User user01 = run.getBean("user1", User.class);
        Pet pet1 = run.getBean("pet1", Pet.class);
    
        System.out.println("依赖:" + (user01.getPet() == pet1));
    

    这里就是判断当proxyBeanMethods = true的情况下,User对象的 pet,是不是容器中的 pet。

    如果是,那么结果就是true

    此时再将proxyBeanMethods = false,重新运行一下,结果会是 false:

    那么这 2 个模式分别在什么时候用呢

    当在你的同一个Configuration配置类中,注入到容器中的 bean 实例之间有依赖关系时,建议使用 Full 全模式

    当在你的同一个Configuration配置类中,注入到容器中的 bean 实例之间没有依赖关系时,建议使用 Lite 轻量级模式,以提高 springboot 的启动速度和性能。

    --不要用肉体的勤奋,去掩盖思考的懒惰--
  • 相关阅读:
    Digital Video Stabilization and Rolling Shutter Correction using Gyroscope 论文笔记
    Distortion-Free Wide-Angle Portraits on Camera Phones 论文笔记
    Panorama Stitching on Mobile
    Natural Image Stitching with the Global Similarity Prior 论文笔记 (三)
    Natural Image Stitching with the Global Similarity Prior 论文笔记(二)
    Natural Image Stitching with the Global Similarity Prior 论文笔记(一)
    ADCensus Stereo Matching 笔记
    Efficient Large-Scale Stereo Matching论文解析
    Setting up caffe on Ubuntu
    Kubernetes配置Secret访问Harbor私有镜像仓库
  • 原文地址:https://www.cnblogs.com/pingguo-softwaretesting/p/15204039.html
Copyright © 2011-2022 走看看