@Configuration中的proxyBeanMethods属性详解

1,076 阅读3分钟

@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; } 1 2 3 4 5 6 7 8 9 新建一个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));
}

}

image.png 当我设置proxyBeanMethods = true时,运行结果为true,显然两次获取的对象是相同的

当我设置proxyBeanMethods = false时,运行结果为false,两次获取的对象并不同:

image.png

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));
}

}

image.png

运行结果: 当我设置proxyBeanMethods = true时,运行结果为true,说明获取到的girl实例中的boyfriend参数和获取到的boy实例是相同的

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

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