【问题标题】:@Bean inside class with @Configuration and without it带有@Configuration 和没有它的类中的@Bean
【发布时间】:2011-03-20 19:49:20
【问题描述】:

Spring 3.0 中有一个@Bean 注解。它允许直接在 Java 代码中定义 Spring bean。在浏览 Spring 参考资料时,我发现了使用此注解的两种不同方式 - 使用 @Configuration 进行注解的类内部和没有此注解的类内部。

This section 包含以下代码:

@Component
public class FactoryMethodComponent {

   @Bean @Qualifier("public")
   public TestBean publicInstance() {
      return new TestBean("publicInstance");
   }

   // omitted irrelevant method
}

And here 我们可以看到一段非常相似的代码,但现在@Configuration 就在这个地方:

@Configuration
public class AppConfig {
   @Bean
   public MyService myService() {
      return new MyServiceImpl();
   }
}

参考的前一部分包含以下解释:

Spring 组件中的 @Bean 方法的处理方式与 Spring @Configuration 类中的对应方法不同。不同之处在于@Component 类没有通过CGLIB 增强来拦截方法和字段的调用。 CGLIB 代理是调用@Configuration 类中的方法或字段的方法@Bean 方法创建对协作对象的bean 元数据引用。不使用正常的 Java 语义调用方法。相反,在@Component 类@Bean 方法中调用方法或字段具有标准的Java 语义。

但是 CGLIB 是一种应用程序开发人员不应该意识到的内部东西(当然,在理想的世界中)。据我了解,在这两种情况下,Spring 都会调用带有 @Bean 注释的方法来创建 Spring bean,在这两种情况下,这些实例都被注入到协作者中。

所以我的问题是作为应用程序开发人员,这两种情况有什么区别

【问题讨论】:

  • 你不能真正忽略 CGLIB 的东西。通过这样做,您可能会得到没有明显意义的奇怪副作用。
  • @skaffman 这就是我添加“在理想世界中”的原因。但我认为 Spring 的整个想法是尽可能多地向应用程序开发人员隐藏内部,尤其是代理机制。

标签: java spring


【解决方案1】:

不同之处在于@Configuration可以调用另一个@Bean方法,得到一个完全初始化的实例,如下:

public class Foo {
    @Value("Hello, world!")
    public String value;
}

@Configuration
public class Config {
    @Bean
    public Foo createFoo() {
        Foo foo = new Foo();
        System.out.println(foo.value); // Prints null - foo not initialized yet
        return foo;
    }

    @Bean
    public Bar createBar() {
        Foo foo = createFoo();
        System.out.println(foo.value); // Prints Hello, world! - foo have been initialized by the interceptor
        return new Bar(foo);
    }
}

【讨论】:

  • 更重要的是,您可以在问题中引用的同一版本的文档的section 3.10.4 的最后一段中找到此行为的参考文档。
【解决方案2】:

@Component 内的@Bean [实例方法] - 一个带有@Bean 实例的方法调用另一个方法@Bean 实例,那么这将是简单的java 语义调用,即Spring 容器不会返回对象,从java实例工厂方法返回正常,因为组件类没有扩展CGLIB。

@Configuration 中的@Bean [实例方法] - 在这种情况下,spring 容器将返回对现有对象的引用。这不会是正常的java语义调用。

@Bean 在配置和组件类中的静态方法上 - 在这种情况下,@Bean 方法将永远不会被容器拦截,无论是在配置类中还是在组件原型类中。

【讨论】:

  • 组件类确实扩展了 CGLIB,否则它们无法使用 AOP。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-06-29
  • 1970-01-01
  • 2016-01-25
  • 1970-01-01
  • 1970-01-01
  • 2013-02-23
  • 2017-03-08
相关资源
最近更新 更多