首页 > 解决方案 > @Configuration 是强制性的吗?

问题描述

在某些情况下,我有一个不能用@Configuration. 一开始我以为它不能工作,因为Spring配置必须有@Configuration注解。但是,在做了一些测试之后,我才意识到@Configuration这不是强制性的。

例如,这是一个没有配置的 Java 类@Configuration

public class NotAnnotatedConfiguration {

    @Bean
    public DemoService demoService() {
        return new DemoService();
    }

}

我尝试在以下测试中加载此配置:

@ContextConfiguration(classes = NotAnnotatedConfiguration.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class NotAnnotatedConfigurationTest {

    @Autowired DemoService demoService;

    @Test
    public void load() {
        assertNotNull(this.demoService);
    }

}

它有效!我在实际应用中得到了相同的结果,而不仅仅是在测试中。

根据我的测试,我认为@Configuration只有当您希望 Spring 扫描类时才有必要这样做,否则您可以为 Spring 提供未注释的配置,它将加载并扫描其中定义的所有 bean。但是,AnnotationConfigApplicationContext的 javadoc 对我来说似乎不太清楚(可能我误解了一些东西):

/**
 * Create a new AnnotationConfigApplicationContext, deriving bean definitions
 * from the given annotated classes and automatically refreshing the context.
 * @param annotatedClasses one or more annotated classes,
 * e.g. {@link Configuration @Configuration} classes
 */
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
    this();
    register(annotatedClasses);
    refresh();
}

我用我的测试创建了一个 github 存储库来分享我的结论:https ://github.com/itelleria/configuration-annotation

问题是,尽管进行了我的测试,是否允许@Configuration在 Spring 中不使用 java 配置类进行注释?

提前致谢。

标签: springspring-java-config

解决方案


我认为你是对的,Spring 将加载配置类并创建实例,但不会将实例视为 bean。含义:使用 的其他服务DemoService将为每次使用创建多个实例,而不是作为作为 bean 创建时的默认范围的单例。

public class DemoServiceUsage {

    DemoService demoService;

    public DemoServiceUsage(DemoService demoService) {
        this.demoService = demoService;
    }
}

public class NotAnnotatedConfiguration {
    @Bean
    public DemoService demoService() {
        DemoService demoService = new DemoService();
        System.out.println("demoService " + demoService.hashCode());
        return demoService;
    }

    @Bean
    public DemoServiceUsage demoServiceUsage1() {
        return new DemoServiceUsage(demoService());
    }

    @Bean
    public DemoServiceUsage demoServiceUsage2() {
        return new DemoServiceUsage(demoService());
    }
}

@Configuration
@Import({
    NotAnnotatedConfiguration.class
})
public class ApplicationConfig {
}

@ContextConfiguration(classes = ApplicationConfiguration.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class NotAnnotatedConfigurationTest {

    @Autowired
    DemoServiceUsage demoServiceUsage1;

    @Autowired
    DemoServiceUsage demoServiceUsage2;

    @Test
    public void load() {
        assertNotNull(this.demoServiceUsage1);
        assertNotNull(this.demoServiceUsage2);
    }
}

在这里,您将看到您获得了多个具有不同 hashCode 的 demoService 输出。如果demoService是一个 bean,我们应该只看到一个实例,因为它应该有一个单例范围。


推荐阅读