@Configuration中的proxyBeanMethods属性详解

@Configuration注释中的proxyBeanMethods参数是springboot1.0,升级到springboot2.0之后新增的比较重要的内容,
该参数是用来代理bean的

1.理论

首先引出两个概念:Full 全模式,Lite 轻量级模式

  • Full(proxyBeanMethods = true) :proxyBeanMethods参数设置为true时即为:Full 全模式。 该模式下注入容器中的同一个组件无论被取出多少次都是同一个bean实例,即单实例对象,在该模式下SpringBoot每次启动都会判断检查容器中是否存在该组件
  • Lite(proxyBeanMethods = false) :proxyBeanMethods参数设置为false时即为:Lite 轻量级模式。该模式下注入容器中的同一个组件无论被取出多少次都是不同的bean实例,即多实例对象,在该模式下SpringBoot每次启动会跳过检查容器中是否存在该组件
    什么时候用Full全模式,什么时候用Lite轻量级模式?
  • 当在你的同一个Configuration配置类中,注入到容器中的bean实例之间有依赖关系时,建议使用Full全模式
  • 当在你的同一个Configuration配置类中,注入到容器中的bean实例之间没有依赖关系时,建议使用Lite轻量级模式,以提高springboot的启动速度和性能

2.实操验证

新建一个Boy类和Girl类

 public class Boy {
    private String name;
    private Integer age;
}
public class Girl {
    private String name;
    private Integer age;
    private Boy boyfriend;
}

新建一个Config类

@Configuration(proxyBeanMethods = true)
public class MyConfiguration {

    @Bean
    public Boy getBoy(){
        Boy boy = new Boy("Jerry",18);
        return Boy;
    }
}

这里就直接把测试代码写到主方法中了,方便启动SpringBoot直接能看到结果

@SpringBootApplication
public class Springboot2StudyApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext run = SpringApplication.run(Springboot2StudyApplication.class, args);
        String[] beanNames = run.getBeanDefinitionNames(); //获取所有注入到容器的组件名字
        for (String beanName : beanNames) {
            System.out.println(beanName);
        }
        MyConfiguration bean = run.getBean(MyConfiguration.class);
        Boy boy1 = bean.getBoy();
        Boy boy2 = bean.getBoy();
        System.out.println( "两次调用的对象是否相等?" +(boy1 == boy2));
    }
}

当我设置proxyBeanMethods = true时,运行结果为true,显然两次获取的对象是相同的
@Configuration中的proxyBeanMethods属性详解_第1张图片
当我设置proxyBeanMethods = false时,运行结果为false,两次获取的对象并不同
@Configuration中的proxyBeanMethods属性详解_第2张图片

Boy类和Girl类是关联的,Girl类中有Boy类型的boyfriend,我们验证下proxyBeanMethods参数对关联组件之间的影响
在config配置类中添加getGirl组件并注入容器中

@Configuration(proxyBeanMethods = true)
public class MyConfiguration {


    @Bean
    public Boy getBoy(){
        Boy boy = new Boy("Jerry",18);
        return boy;
    }
    @Bean
    public Girl getGirl(){
        Girl girl = new Girl();
        girl.setName("Susan");
        girl.setAge(18);
        girl.setBoyfriend(getBoy());
        return girl;
    }
}

依然在主启动类中测试

@SpringBootApplication
public class Springboot2StudyApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext run = SpringApplication.run(Springboot2StudyApplication.class, args);
        MyConfiguration bean = run.getBean(MyConfiguration.class);

        Boy boy = bean.getBoy();
        Girl girl = bean.getGirl();
        System.out.println("该女生有只有一个男朋友吗?" + (girl.getBoyfriend() == boy));
    }
}

运行结果:
当我设置proxyBeanMethods = true时,运行结果为true,说明获取到的girl实例中的boyfriend参数和获取到的boy实例是相同的
@Configuration中的proxyBeanMethods属性详解_第3张图片

当我设置proxyBeanMethods = false时,运行结果为false,说明获取到的girl实例中的boyfriend参数和获取到的boy实例不同,该女生居然有两个男朋友,渣女一枚鉴定完毕!~
@Configuration中的proxyBeanMethods属性详解_第4张图片

3.总结

  • Full 全模式,proxyBeanMethods默认是true:使用代理,也就是说该配置类会被代理,直接从IOC容器之中取得bean对象,不会创建新的对象。SpringBoot总会检查这个组件是否在容器中是否存在,保持组件的单实例
  • Lite 轻量级模式,proxyBeanMethods设置为false:每次调用@Bean标注的方法获取到的对象是一个新的bean对象,和之前从IOC容器中获取的不一样,SpringBoot会跳过检查这个组件是否在容器中是否存在,保持组件的多实例

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