在 Spring java 配置中调用 @Bean 注释方法
Calling a @Bean annotated method in Spring java configuration
我很好奇 spring 注入如何处理带有 @Bean
注释的调用方法。如果我在一个方法上放置一个 @Bean
注释,并在一个实例上放置 return,我明白这告诉 spring 通过调用该方法并获取 returned 创建一个 bean实例。但是,有时该 bean 必须用于连接其他 bean 或设置其他代码。完成此操作的通常方法是调用 @Bean
注释方法来获取实例。我的问题是,为什么这不会导致有多个 bean 实例浮动?
例如,请参阅下面的代码(摘自另一个问题)。 entryPoint()
方法用 @Bean
注释,所以我想 spring 将创建一个新的 BasicAuthenticationEntryPoint
实例作为 bean。然后,我们在 configure 块中再次调用 entryPoint()
,但似乎 entryPoint()
return 是 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.
我很好奇 spring 注入如何处理带有 @Bean
注释的调用方法。如果我在一个方法上放置一个 @Bean
注释,并在一个实例上放置 return,我明白这告诉 spring 通过调用该方法并获取 returned 创建一个 bean实例。但是,有时该 bean 必须用于连接其他 bean 或设置其他代码。完成此操作的通常方法是调用 @Bean
注释方法来获取实例。我的问题是,为什么这不会导致有多个 bean 实例浮动?
例如,请参阅下面的代码(摘自另一个问题)。 entryPoint()
方法用 @Bean
注释,所以我想 spring 将创建一个新的 BasicAuthenticationEntryPoint
实例作为 bean。然后,我们在 configure 块中再次调用 entryPoint()
,但似乎 entryPoint()
return 是 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.