首页 文章

了解spring @Configuration类

提问于
浏览
96

关于问题Understanding Spring @Autowired usage我想为 spring 布线的另一个选项 @Configuration 类创建一个完整的知识库 .

假设我有一个如下所示的spring XML文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

  <import resource="another-application-context.xml"/>

  <bean id="someBean" class="stack.overflow.spring.configuration.SomeClassImpl">
    <constructor-arg value="${some.interesting.property}" />
  </bean>

  <bean id="anotherBean" class="stack.overflow.spring.configuration.AnotherClassImpl">
    <constructor-arg ref="someBean"/>
    <constructor-arg ref="beanFromSomewhereElse"/>
  </bean>
</beans>

我怎样才能使用 @Configuration ?它对代码本身有什么影响吗?

1 回答

  • 135

    将XML迁移到@Configuration

    可以通过几个步骤将xml迁移到 @Configuration

    • 创建 @Configuration 带注释的类:
    @Configuration
    public class MyApplicationContext {
    
    }
    
    • 对于每个 <bean> 标记,创建一个使用 @Bean 注释的方法:
    @Configuration
    public class MyApplicationContext {
    
      @Bean(name = "someBean")
      public SomeClass getSomeClass() {
        return new SomeClassImpl(someInterestingProperty); // We still need to inject someInterestingProperty
      }
    
      @Bean(name = "anotherBean")
      public AnotherClass getAnotherClass() {
        return new AnotherClassImpl(getSomeClass(), beanFromSomewhereElse); // We still need to inject beanFromSomewhereElse
      }
    }
    
    • 为了导入 beanFromSomewhereElse 我们需要导入它's definition. It can be defined in an XML and the we' ll使用 @ImportResource
    @ImportResource("another-application-context.xml")
    @Configuration
    public class MyApplicationContext {
      ...  
    }
    

    如果bean在另一个 @Configuration 类中定义,我们可以使用 @Import 注释:

    @Import(OtherConfiguration.class)
    @Configuration
    public class MyApplicationContext {
      ...
    }
    
    • 在导入其他XML或 @Configuration 类之后,我们可以通过向 @Configuration 类声明私有成员来使用它们在我们的上下文中声明的bean,如下所示:
    @Autowired
    @Qualifier(value = "beanFromSomewhereElse")
    private final StrangeBean beanFromSomewhereElse;
    

    或者直接将它用作方法中的参数,该方法使用 @Qualifier 定义依赖于此 beanFromSomewhereElse 的bean,如下所示:

    @Bean(name = "anotherBean")
    public AnotherClass getAnotherClass(@Qualifier (value = "beanFromSomewhereElse") final StrangeBean beanFromSomewhereElse) {
      return new AnotherClassImpl(getSomeClass(), beanFromSomewhereElse);
    }
    
    • 导入属性与从另一个xml或 @Configuration 类导入bean非常相似 . 我们不会使用 @Qualifier ,而是使用 @Value ,其属性如下:
    @Autowired
    @Value("${some.interesting.property}")
    private final String someInterestingProperty;
    

    这也可以与 SpEL 表达式一起使用 .

    • 为了允许spring将这些类视为bean容器,我们需要在主xml中将此标记放在上下文中:
    <context:annotation-config/>
    

    您现在可以导入 @Configuration 类与创建简单bean完全相同:

    <bean class="some.package.MyApplicationContext"/>
    

    有一些方法可以完全避免使用Spring XML,但它们不在本答案的范围内 . 您可以在我的blog post中找到其中一个选项,我的答案基于这些选项 .


    使用此方法的优缺点

    基本上我发现这种声明bean的方法比使用XML更舒服,因为我看到了一些优点:

    • Typos - @Configuration 类被编译,错别字只是不允许编译

    • Fail fast (compile time) - 如果你忘记注入一个bean,你将在编译时失败,而不是像XML一样在运行时

    • Easier to navigate in IDE - 在bean的构造函数之间理解依赖树 .

    • Possible to easily debug configuration startup

    我看到它们的缺点并不多,但有一些我能想到的:

    • Abuse - 代码比XML更容易被滥用

    • 使用XML,您可以基于在编译期间不可用但在运行时提供的类来定义依赖项 . 使用 @Configuration 类,您必须在编译时提供类 . 通常这不是问题,但有些情况可能会发生 .

    结论:在您的应用程序上下文中组合XML, @Configurationannotations是完美的 . Spring并不关心声明bean的方法 .

相关问题