【问题标题】:Are all Spring Framework Java Configuration injection examples buggy?所有 Spring Framework Java 配置注入示例都有问题吗?
【发布时间】:2013-12-31 22:37:28
【问题描述】:

我想知道是只有我自己还是大多数 Spring 的 Java 配置示例有缺陷?比如这里:

http://spring.io/blog/2008/03/27/spring-java-configuration-what-s-new-in-m3 http://spring.io/blog/2013/07/18/javaconfig-support-in-the-spring-tool-suite

注意他们是如何注入 bean 的?他们直接使用方法,例如:new OrderRepository(dataSource()) 这里:

@Configuration
public class ApplicationConfig {

    public @Bean OrderRepository orderRepository() {
        return new OrderRepository(dataSource());
    }

    public @Bean DataSource dataSource() {
        // instantiate and return an new DataSource ...
    }
}

这让我想到 - 如果使用两次,它不会创建两个对象吗?有效绕过Spring的单例保证?他们为什么不注射豆子呢?因为依赖框架最初是为工作而设计的。

让我们做一个快速测试。以这两个类为例 - TestParent 和 TestedChild。家长接受孩子:new TestParent(new TestedChild())。我们将在一分钟内将它们制作成单例 bean。

public class TestedChild { }

public class TestParent {

    private TestedChild child;

    public TestParent(TestedChild child) {
        this.child = child;
    }

    public TestedChild getChild() { return child; }

}

我想看看我们是否真的可以在上下文初始化期间创建两个不同的 TestedChild 实例。现在让我们配置我们的单例 bean:

@Configuration
public class TestInjectionConfig {

    @Bean(name = "injected")
    public TestParent injected(TestedChild bean) {
        return new TestParent(bean);
    }

    @Bean(name = "direct")
    public TestParent direct() {
        return new TestParent(testedBean());
    }

    @Bean
    public TestedChild testedBean() {
        return new TestedChild();
    }

}

我正在创建两个不同的 TestParent 对象,它们应该在创建时注入相同的 TestedChild。

让我们测试一下:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TestInjectionConfig.class)
public class InjectionApplicationTest {

    @Inject @Named("injected")
    TestParent injected;

    @Inject @Named("direct")
    TestParent direct;

    @Test
    public void instancesShouldBeTheSame() {

        Assert.assertSame(injected, direct);

    }

}

我希望 bean 是相同的,但这是我在 Spring 3.2.6 上得到的:

junit.framework.AssertionFailedError: expected same:<pl.aie.TestParent@59e5a42c> was not:<pl.aie.TestParent@737d72cf>

回到问题。为什么示例在 Spring 配置类上使用直接方法调用?如果它们是这样被调用的,为什么用 @Bean 注释来注释它们?这是一种不好的做法,还是我的逻辑/代码有缺陷?

【问题讨论】:

  • 我不知道为什么人们不赞成这个...并投票关闭主要基于意见的???

标签: java spring dependency-injection spring-java-config


【解决方案1】:

在您的测试中,您正在比较两个 TestParent bean,而不是单个 TestedChild bean。

此外,Spring 代理您的 @Configuration 类,因此当您调用 @Bean 注释方法之一时,它会缓存结果并在以后的调用中始终返回相同的对象。

看这里:

【讨论】:

  • 请注意,@Configuration 的 Spring 代理行为与 @Transactional 等常用代理不同,并且会拦截自调用。
  • 哦,原来如此。代码应为:Assert.assertSame(injected.getChild(), direct.getChild());。我的错。谢谢大家。
  • @MichałMinicki 不客气。 Spring 文档中的 IOC 章节解释了大部分内容,并提供了使用 Java 配置上下文的提示和技巧。
  • 我上次阅读该部分文档时,Spring 的 JavaConfig 还没有诞生。我什至不确定我们当时是否已经有该语言的注释。但再次感谢:)
  • 这是解释一切的手册条目 (3.11.5):docs.spring.io/spring/docs/3.0.x/reference/…
猜你喜欢
  • 2011-01-18
  • 1970-01-01
  • 1970-01-01
  • 2011-12-05
  • 2017-09-23
  • 1970-01-01
  • 2016-12-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多