当前位置: 首页 > 面试题库 >

在Spring Java配置中调用@Bean带注释的方法

吕冠宇
2023-03-14
问题内容

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

例如,请参见下面的代码(取自另一个问题)。该entryPoint()方法带有注释@Bean,因此我可以想象spring将创建一个BasicAuthenticationEntryPointas的新实例。然后,我们entryPoint()在configure块中再次调用,但是似乎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

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

这意味着@Bean通过CGLIB代理对方法的调用,因此将返回Bean的缓存版本(不创建新的)。

@Beans 的默认范围是SINGLETON,如果您指定其他范围,例如PROTOTYPE调用将传递给原始方法。

请注意,这 对于静态方法无效 。根据春季文件:

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



 类似资料:
  • 我很好奇spring注入是如何用注释处理调用方法的。如果我将注释放在一个方法上,并返回一个实例,我理解这会告诉spring通过调用该方法并获得返回的实例来创建一个bean。但是,有时该bean必须用于连接其他bean或设置其他代码。通常的方法是调用带注释的方法来获得一个实例。我的问题是,为什么这不会导致bean的多个实例浮动? 例如,参见下面的代码(摘自另一个问题)。方法是用注释的,因此我想spr

  • 在Spring Hibernate XML配置中,我有 我知道SpringJava配置的等价物如下:LocalSessionFactoryBuilder(dataSource())。AddAnnotatedClass(Foo.class)。buildSessionFactory(); 我的问题是,如果我不使用LocalSessionFactoryBuilder类,而是使用HibernateJpaV

  • 我知道从中调用带注释的方法,前面已经讨论过了。 但是我不明白为什么当bean被覆盖时它就不起作用了。 我有一个遗留类,我不能修改。它是一个配置,同时也是一个业务bean。这是一个简化版本: 现在,调用返回而不是。 当配置被删除并且测试上下文的配置被设置为时,一切都能正常工作(结果为)。 在测试中注册bean有什么不同?

  • 下面的@Retryable代码适用于直接调用方法的情况,但通过@Async annotated method调用Retryable方法会引发异常。有什么建议吗? 这是我的服务课 这是Junit测试类 这里是Spring Boot应用程序类 例外如下。请对此提出任何建议。 retryWithException-0

  • 问题内容: 有人可以给MWE 直接在方法上使用注释的方法吗? 我已经看到了无数的关于在类定义中使用它的示例-但还没有方法的示例。 引用文档: 这种添加到一个类定义或 一个方法 @Target(value = {TYPE, METHOD }) 因此,我认为还有一种可能性和预期的用途-但不幸的是,我无法弄清楚。 问题答案: 这里的DataSource类具有属性url,用户名,密码,driverClas

  • 我正在学习Spring boot+oauth2+JWT,在AuthorizationServerConfig.class(或其他一些配置类)中,我注意到在许多示例中,它们使用@bean注释修饰一些方法,并将方法设置为'public'。对于ExMaple: 如果我删除Bean注释并使方法私有,我的应用程序仍然可以工作。所以我的问题是,为什么我们需要Bean注释和public方法?