在Spring java配置中调用@Bean注释方法 [英] Calling a @Bean annotated method in Spring java configuration

查看:202
本文介绍了在Spring java配置中调用@Bean注释方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很好奇spring spring如何处理使用 @Bean 注释调用方法。如果我在方法上放置一个 @Bean 注释,并返回一个实例,我理解这会告诉spring通过调用方法并获取返回的实例来创建bean。但是,有时该bean必须用于连接其他bean或设置其他代码。通常的方法是调用 @Bean 带注释的方法来获取实例。我的问题是,为什么这不会导致bean的多个实例浮动?

I'm curious about how spring injection handles calling methods with the @Bean annotation. If I put a @Bean annotation on a method, and return an instance, I understand that that tells spring to create a bean by calling the method and getting the returned instance. However, sometimes that bean has to be used to wire other beans or setup other code. The usual way this is done is to call the @Bean annotated method to get an instance. My question is, why doesn't this cause there to be multiple instances of the bean floating around?

例如,请参阅下面的代码(取自另一个问题)。 entryPoint()方法用 @Bean 注释,所以我想spring会创建一个<$的新实例c $ c> BasicAuthenticationEntryPoint 作为bean。然后,我们在配置块中再次调用 entryPoint(),但似乎 entryPoint()返回bean实例,并没有多次调用(我尝试记录,只有一个日志条目)。我们可能会在配置的其他部分多次调用 entryPoint(),并且我们总是会获得相同的实例。我对此的理解是否正确? spring是否会对使用 @Bean 注释的方法进行一些神奇的重写?

For example, see the code below (taken from another question). The entryPoint() method is annotated with @Bean, so I would imagine spring will create a new instance of BasicAuthenticationEntryPoint as a bean. Then, we call entryPoint() again in the configure block, but it seems like entryPoint() returns the bean instance, and isn't called multiple times (I tried logging, and only got one log entry). Potentially we could call entryPoint() multiple times in other parts of the configuration, and we would always get the same instance. Is my understanding of this correct? Does spring do some magical rewriting of methods annotated with @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

Yes, Spring does some magic. Check the Spring Docs:


这就是神奇的地方:所有 @Configuration 使用 CGLIB 在启动时对类进行子类化。在子类中,子方法在调用父方法并创建新实例之前首先检查容器是否有任何缓存(作用域)bean。

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的缓存版本(未创建新版本)。

This means that your the calls to @Bean methods are proxied via CGLIB and therefore the cached version of the bean is returned (a new one is not created).

<$ c $的默认范围c> @Bean s是 SINGLETON ,如果指定其他范围,例如 PROTOTYPE 该调用将传递给原始方法。

The default scope of @Beans is SINGLETON, if you specify a different scope such as PROTOTYPE the call will be passed to the original method.

请注意,对静态方法无效。根据spring docs:

Please note that this is not valid for static methods. As per the spring docs:


调用静态 @Bean 方法永远不会被截获由于技术限制,容器甚至不在 @Configuration 类中(如本节前面所述):CGLIB子类化只能覆盖非静态方法。因此,直接调用另一个 @Bean 方法具有标准的Java语义,从而导致直接从工厂方法本身返回一个独立的实例。

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 java配置中调用@Bean注释方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆