如何对在JavaConfig中定义更多@Beans的@Configuration类进行后处理?

时间:2015-07-30 18:21:00

标签: spring spring-java-config

在Spring XML中,我可以定义一个bean,它实例化一个用@Configuration注释的类。当我这样做时,该bean被后处理。该类中带有@Bean的任何方法也会添加到容器中。如何在JavaConfig中执行类似的后处理?

这是XML版本:

<bean id="test" class="com.so.Test">
    <property name="prop" value="set before instantiating @Beans defined in Test"/>
</bean>

相关的测试类:

@Configuration
class Test {
    private String prop;

    void setProp(final String prop) {
        this.prop = prop;
    }

    @Bean
    NeedThisBean needThisBeanToo() {
        return new NeedThisBean(prop);
    }
}

如果我使用Spring XML Config,容器中可以使用testneedThisBeanTooneedThisBeanToo是通过BeanPostProcessor添加的,虽然我不记得是哪一个。如果我使用JavaConfig,则容器中只有test可用。如何使needThisBeanToo可用于容器? @Import可以正常工作,除了prop需要needThisBeanToo才能正确初始化。

使所有这些变得复杂的部分是Test从我正在消费的库中出售。我不控制Test,也不能改变它。如果我从JavaConfig驱动它,它将如下所示:

@Configuration
class MyConfiguration
{
    @Bean
    Test test() {
        Test test = new Test();
        test.setProp("needed to init `needThisBeanToo` and others");
        return test;
    }
}

JavaConfig示例不会实例化needThisBeanToo,尽管它是在Test中定义的。我需要定义needThisBeanToo,最好不要自己做,因为我不想复制我不拥有的代码。委托不具吸引力,因为needThisBeanToo上定义了许多后续注释/范围(以及Test内定义的其他注释/范围)。

2 个答案:

答案 0 :(得分:0)

您的问题是,您完全忽略 @Configuration注释。那是为什么?

当代码到达此行Test test = new Test();时,它不会对@Configuration执行任何操作。为什么?因为注释不是构造函数知道的东西。注释仅标记该类的一些元数据。当spring加载类时,它会搜索注释,当你调用类的构造函数时,则不会。因此,@Configuration被忽略,因为您使用Test而不是通过spring实例化new Test()

您需要做的是将Test导入为spring bean。您可以通过问题中显示的XML或@Import使用XML。 prop的问题是没有调用setter,因为这不是这样做的方法。你需要做的是做这样的事情:

@Configuration
class Test {
  private String prop = "set before instantiating @Beans defined in Test";

  @Bean
  NeedThisBean needThisBeanToo() {
      return new NeedThisBean(prop);
  }
}

或者在spring中创建一个属性(这是一个不同的主题)并注入值:

@Configuration
class Test {
  @Autowired
  @Value("${some.property.to.inject}") // You can also use SPeL syntax with #{... expression ...}
  private String prop;

  @Bean
  NeedThisBean needThisBeanToo() {
      return new NeedThisBean(prop);
  }
}

您还可以创建类型为String的bean,并按如下方式注入:

@Configuration
class Test {
  @Autowired
  @Qualifer("nameOfBeanToInject")
  private String prop;

  @Bean
  NeedThisBean needThisBeanToo() {
      return new NeedThisBean(prop);
  }
}

在最后一种情况下,您可以使用此bean定义原始MyConfiguration

@Configuration
@Import(Test.class)
class MyConfiguration
{
    @Bean(name = "nameOfBeanToInject")
    String test() {
        return "needed to init `needThisBeanToo` and others";
    }
}

在任何情况下,您都必须使用Test或普通的XML bean导入@Import。通过显式调用构造函数它将无法工作。

答案 1 :(得分:0)

这是一种处理已售出的@Configuration类的方法,这些类需要在创建@Beans之前设置一些属性:

Vended @Configuration类:

@Configuration
class Test {

    private String property;

    public setProperty(final String property) {
        this.property = property;
    }

    @Bean
    PropertyUser propertyUser() {
        return new PropertyUser(property);
    }

    @Bean
    SomeBean someBean() {
        // other instantiation logic
        return new SomeBeanImpl();
    }
}

这是消费的@Configuration类:

@Configuration
class MyConfig {

    @Bean
    static String myProperty() {
        // Create myProperty
    }

    /**
     * Extending Test allows Spring JavaConfig to create
     * the beans provided by Test.  Declaring
     * Test as a @Bean does not provide the @Beans defined
     * within it.
     */
    @Configuration
    static class ModifiedTest extends Test {

        ModifiedTest() {
            this.setProperty(myProperty());
        }

        @Override
        @Bean
        SomeBean someBean() {
            return new SomeBeanCustomImpl(this.propertyUser());
    }
}