@Configuration(proxyBeanMethods = true/false)
1、Full模式(proxyBeanMethods=true)
proxyBeanMethods=true 为Full模式(默认为true),此时在spring IOC容器中的此配置类是一个CGLIB代理类,并且调用此配置类的@Bean方法产生的bean是单例的,即每次调用标有@Bean注解方法都会检查IOC容器中是否有该bean组件,如果没有则调用方法创建,否则就直接从IOC容器中获取。
测试代码
1 2 3 4 5 6 7
| @Configuration(proxyBeanMethods = true) public class ProxyBeanMethodTest { @Bean public User user(){ return new User(); } }
|
1 2 3 4 5 6 7 8 9 10 11 12
| @SpringBootApplication public class MainApplication { public static void main(String[] args){ ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args); ProxyBeanMethodTest bean = run.getBean(ProxyBeanMethodTest.class); System.out.println("配置类:"+bean); User user1 = bean.user(); User user2 = bean.user(); System.out.println("第一次调用配置类中的@Bean注解方法得到的bean组件:"+user1); System.out.println("第二次调用配置类中的@Bean注解方法得到的bean组件:"+user2); } }
|
运行结果
两次调用user()方法得到的是同一个user对象
2、Lite模式(proxyBeanMethods=false)
proxyBeanMethods=false 为Lite模式,此时在spring IOC容器中此配置类就是一个普通的类,每次调用此配置类中标有@Bean注解的方法时都会在IOC容器中注册新的bean组件,调用@Bean方法时无需检查IOC容器中是否存在该bean组件,可以提高效率,加速容器启动
测试代码
1 2 3 4 5 6 7
| @Configuration(proxyBeanMethods = false) public class ProxyBeanMethodTest { @Bean public User user(){ return new User(); } }
|
1 2 3 4 5 6 7 8 9 10 11 12
| @SpringBootApplication public class MainApplication { public static void main(String[] args){ ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args); ProxyBeanMethodTest bean = run.getBean(ProxyBeanMethodTest.class); System.out.println("配置类:"+bean); User user1 = bean.user(); User user2 = bean.user(); System.out.println("第一次调用配置类中的@Bean注解方法得到的bean组件:"+user1); System.out.println("第二次调用配置类中的@Bean注解方法得到的bean组件:"+user2); } }
|
运行结果
两次调用user()方法得到的是不同的User对象
3、Full模式和Lite模式优劣比较
Full模式可以很好地处理组件之间相互依赖的问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @Configuration(proxyBeanMethods = true) public class ProxyBeanMethodTest {
@Bean public User user(){ User user = new User(); user.setDog(dog()); return user; }
@Bean public Dog dog(){ return new Dog(); } }
|
1 2 3 4 5 6 7 8 9 10 11 12
| @SpringBootApplication public class MainApplication {
public static void main(String[] args) { ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args); User user = run.getBean(User.class); Dog dog1 = user.getDog(); Dog dog2 = run.getBean(Dog.class); System.out.println(dog1 == dog2); } }
|
由以上结果可以看出,IOC容器中的Dog与User的属性Dog是同一个对象,也更加印证了当为User对象注入Dog属性时,此Dog是从IOC容器中获取的,而并非重新调用了dog()方法。从上面的测试代码中也可以看出,使用Full模式可以确保IOC容器中同一类型的对象始终是同一个,可以很好的处理组件依赖问题。
Lite模式免去了每次调用方法前去IOC容器中检查的过程,可以有效加速容器启动过程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @Configuration(proxyBeanMethods = true) public class ProxyBeanMethodTest {
@Bean public User user(){ User user = new User(); user.setDog(dog()); return user; }
@Bean public Dog dog(){ return new Dog(); } }
|
1 2 3 4 5 6 7 8 9 10 11 12
| @SpringBootApplication public class MainApplication {
public static void main(String[] args) { ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args); User user = run.getBean(User.class); Dog dog1 = user.getDog(); Dog dog2 = run.getBean(Dog.class); System.out.println(dog1 == dog2); } }
|
4、结论
- 配置类组件之间无依赖关系时使用Lite模式,可以省去检查容器中是否已经存在同类型组件的过程,加速容器启动
- 配置类组件之间有依赖关系,使用Full模式,方法调用得到容器中的单实例组件
友情链接
视频讲解内容可参考尚硅谷-SpringBoot2讲解视频:https://www.bilibili.com/video/BV19K4y1L7MT?p=8