我很好奇spring注入(inject)如何处理带有@Bean
注解的调用方法。如果我在方法上放置 @Bean
注释并返回一个实例,我知道这会告诉 spring 通过调用该方法并获取返回的实例来创建一个 bean。但是,有时该 bean 必须用于连接其他 bean 或设置其他代码。这样做的通常方法是调用 @Bean
带注释的方法来获取实例。我的问题是,为什么这不会导致 bean 出现多个实例?
例如,请参见下面的代码(取自另一个问题)。 entryPoint()
方法用 @Bean
注释,所以我想 spring 会创建一个新的 BasicAuthenticationEntryPoint
实例作为 bean。然后,我们在配置 block 中再次调用 entryPoint()
,但似乎 entryPoint()
返回了 bean 实例,并且没有被多次调用(我尝试记录,并且只有一个日志条目)。潜在地,我们可以在配置的其他部分多次调用 entryPoint()
,而我们总是会得到相同的实例。我对此的理解正确吗? Spring 是否会对带有 @Bean
注释的方法进行一些神奇的重写?
@Bean
public BasicAuthenticationEntryPoint entryPoint() {
BasicAuthenticationEntryPoint basicAuthEntryPoint = new BasicAuthenticationEntryPoint();
basicAuthEntryPoint.setRealmName("My Realm");
return basicAuthEntryPoint;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.exceptionHandling()
.authenticationEntryPoint(entryPoint())
.and()
.authorizeUrls()
.anyRequest().authenticated()
.and()
.httpBasic();
}
最佳答案
是的,Spring 确实有一些魔法。查看Spring Docs :
This is where the magic comes in: All
@Configuration
classes are subclassed at startup-time with CGLIB. In the subclass, the child method checks the container first for any cached (scoped) beans before it calls the parent method and creates a new instance.
这意味着对 @Bean
方法的调用是通过 CGLIB 代理的。因此会返回 bean 的缓存版本(不会创建新版本)。
@Bean
s 的默认作用域是 SINGLETON
,如果你指定一个不同的作用域例如 PROTOTYPE
调用将被传递给原始方法。
请注意,这对静态方法无效。根据 Spring 文档:
Calls to static
@Bean
methods never get intercepted by the container, not even within@Configuration
classes (as described earlier in this section), due to technical limitations: CGLIB subclassing can override only non-static methods. As a consequence, a direct call to another@Bean
method has standard Java semantics, resulting in an independent instance being returned straight from the factory method itself.
关于java - 在 Spring java 配置中调用 @Bean 注解的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27990060/