@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,显然两次获取的对象是相同的
当我设置proxyBeanMethods = false时,运行结果为false,两次获取的对象并不同
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实例是相同的
当我设置proxyBeanMethods = false时,运行结果为false,说明获取到的girl实例中的boyfriend参数和获取到的boy实例不同,该女生居然有两个男朋友,渣女一枚鉴定完毕!~
3.总结
- Full 全模式,proxyBeanMethods默认是true:使用代理,也就是说该配置类会被代理,直接从IOC容器之中取得bean对象,不会创建新的对象。SpringBoot总会检查这个组件是否在容器中是否存在,保持组件的单实例
- Lite 轻量级模式,proxyBeanMethods设置为false:每次调用@Bean标注的方法获取到的对象是一个新的bean对象,和之前从IOC容器中获取的不一样,SpringBoot会跳过检查这个组件是否在容器中是否存在,保持组件的多实例