java - 在 Spring java 配置中调用 @Bean 注解的方法

标签 java spring cglib

我很好奇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 的缓存版本(不会创建新版本)。

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

相关文章:

java - CGLIB 无法拦截父类(super class)/超接口(interface)中的方法

java - Java中如何将子类中的方法传递给主类

java - Maven + Jboss + SmartGWT 应用程序

java - "org.zuinnote.spark.office.excel"包中未写入空值

java - 尽管正确提供了角色,Spring Security 授权仍无法正常工作

java - Spring XML 处理程序映射

java - 如何查找方法中调用的所有方法(包括 Lamda)?

java - 对于复杂的多模块 Java 应用程序的国际化,您推荐的工具套件是什么?

java - 为什么 Spring INFO 记录到标准错误?

java - Failed to redefine class 当我尝试重新转换类时