使用@Configuration在@Bean内部进行操作

wax*_*wax 5 java spring

@BeanSpring 3.0中有一个注释.它允许直接在Java代码中定义Spring bean.在浏览Spring引用时,我发现了两种使用此注释的不同方法 - 使用带有注释的内部类@Configuration和没有此注释的内部类.

本节包含以下代码:

@Component
public class FactoryMethodComponent {

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

   // omitted irrelevant method
}
Run Code Online (Sandbox Code Playgroud)

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

@Configuration
public class AppConfig {
   @Bean
   public MyService myService() {
      return new MyServiceImpl();
   }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

所以我的问题是,作为两个案例之间的应用程序开发人员,我什么不同

axt*_*avt 11

区别在于@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);
    }
}
Run Code Online (Sandbox Code Playgroud)


Shi*_*arg 6

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

@Bean [instance method] inside @Configuration - 在这种情况下,spring 容器将返回对现有对象的引用。它不会是普通的 java 语义调用。

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