查看 spring 自动配置时 source code似乎每个自动配置类都设置 proxyBeanMethods = false
。
@Configuration(proxyBeanMethods=false)
public class SomeAutoConfiguration {
...
}
javadoc 给出了这个特定字段的详细解释:
Specify whether {@code @Bean} methods should get proxied in order to enforce bean lifecycle behavior, e.g. to return shared singleton bean instances even in case of direct {@code @Bean} method calls in user code. (...) If this is not needed since each of this particular configuration's {@code @Bean} methods is self-contained and designed as a plain factory method for container use, switch this flag to {@code false} in order to avoid CGLIB subclass processing.(...)
读完本文后,我仍然很困惑什么时候将其设置为 false 更好。
这是我的问题:
- 有人可以举一个具体的例子,说明该字段何时应该为真并解释原因吗?
- 为什么在自动配置类上此字段设置为 false?
更新:
在 github 上发现了两个问题,它们给出了为什么大多数自动配置类上的 false
的一些解释:
最佳答案
类似这样的事情:
@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对 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);
}
}
关于java - 何时在 Springs @Configuration 中将 proxyBeanMethods 设置为 false?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61266792/