当查看 spring 自动配置时源代码 https://github.com/spring-projects/spring-boot/tree/master/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure似乎每个自动配置类都设置proxyBeanMethods = false
.
@Configuration(proxyBeanMethods=false)
public class SomeAutoConfiguration {
...
}
javadoc 给出了这个特定字段的详细解释:
指定是否应代理 {@code @Bean} 方法以强制执行
bean 生命周期行为,例如甚至返回共享的单例 bean 实例
如果在用户代码中直接调用 {@code @Bean} 方法。 (...)
如果不需要这样做,因为每个特定配置的 {@code @Bean}
方法是独立的,被设计为容器使用的简单工厂方法,
将此标志切换为 {@code false} 以避免 CGLIB 子类处理。(...)
读完这篇文章后,我仍然很困惑什么时候最好将其设置为 false。
这是我的问题:
- 有人可以给出一个具体的例子,这个字段何时应该为真并解释原因?
- 为什么在自动配置类上此字段设置为 false?
Update:在 github 上发现了两个问题,给出了一些解释为什么会这样false
在大多数自动配置类上:
- https://github.com/spring-projects/spring-boot/issues/9068 https://github.com/spring-projects/spring-boot/issues/9068
-
https://github.com/spring-projects/spring-framework/issues/22461 https://github.com/spring-projects/spring-framework/issues/22461
像这样的事情:
@Configuration(proxyBeanMethods=true)
public class SomeConfiguration {
@Bean
ServiceA serviceA(){
return new ServiceA(sharedService());
}
@Bean
ServiceB serviceB(){
return new ServiceB(sharedService());
}
@Bean
ServiceC sharedService(){
return new ServiceC();
}
}
在这里,proxyBeanMethods 将确保“sharedService”方法将被拦截并重用其结果。如果按照正常的java逻辑,当调用serviceA()和serviceB()时,将有两个不同的ServiceC实例,而当直接调用sharedService()时,将创建第三个实例。然后代理拦截器将确保实际方法只被调用一次,因此只创建一个共享ServiceC的实例,并且ServiceA和ServiceB都将获得共享实例。
不过 proxyBeanMethods=true 在启动时会有性能消耗,特别是对于有很多 @Configuration 类的库,比如 spring-boot 的内部库。参见例如https://github.com/spring-projects/spring-boot/issues/9068#issuecomment-461520814 https://github.com/spring-projects/spring-boot/issues/9068#issuecomment-461520814对 Spring WebFlux 的影响。
默认情况下他们无法将其更改为 false,因为这会破坏向后兼容性。请参阅原始问题中的链接。
您可以使用不同的配置模式来避免这种情况,这可能就是自动配置类所做的。
实现此目的的一种方法是通过方法参数而不是嵌套方法调用自动装配服务。它在普通 Java 中意义不大,但在 Spring 配置中有效:
@Configuration(proxyBeanMethods=false)
public class SomeSmarterConfiguration {
@Bean
ServiceC sharedService(){
return new ServiceC();
}
@Bean
ServiceA serviceA(ServiceC sharedService){
return new ServiceA(sharedService);
}
@Bean
ServiceB serviceB(ServiceC sharedService){
return new ServiceB(sharedService);
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)