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

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

问题描述

我很好奇 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 会创建一个 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 文档:

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 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).

@Beans 的默认作用域是 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 文档:

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天全站免登陆