将Spring XML文件转换为Spring @Configuration类

下面的问题了解Spring @Autowired的用法,我想创build一个完整的知识库,用于弹簧布线的另一个选项@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 ? 它对代码本身有什么影响吗?

(免责声明 – 这个答案是基于我的博客文章 )

将XML迁移到@Configuration

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

  1. 创build一个@Configuration注释类:

     @Configuration public class MyApplicationContext { } 
  2. 对于每个<bean>标签,创build一个用@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 } } 
  3. 为了导入beanFromSomewhereElse我们需要导入它的定义。 它可以在XML中定义,我们将使用@ImportResource

     @ImportResource("another-application-context.xml") @Configuration public class MyApplicationContext { ... } 

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

     @Import(OtherConfiguration.class) @Configuration public class MyApplicationContext { ... } 
  4. 在我们导入其他XML或@Configuration类之后,我们可以使用它们在我们的上下文中声明的bean,方法是将私有成员声明为@Configuration类,如下所示:

     @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); } 
  5. 导入属性与从另一个xml或@Configuration类导入bean非常相似。 我们将使用具有以下属性的@Value ,而不是使用@Qualifier

     @Autowired @Value("${some.interesting.property}") private final String someInterestingProperty; 

    这也可以用于SpELexpression式。

  6. 为了让spring能够像bean容器一样处理类,我们需要在上下文中放置这个标记来在我们的主要xml中标记这个:

     <context:annotation-config/> 

    你现在可以像创build一个简单的bean一样导入@Configuration类:

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

    有许多方法可以完全避免使用Spring XML,但它们不在本答案的范围之内。 你可以在我的博客文章中find其中的一个选项,我正在根据我的答案。


使用这种方法的优点和缺点

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

  1. 错别字@Configuration类被编译和错别字不会允许编译
  2. 快速失败(编译时) – 如果您忘记注入一个bean,那么在编译时会失败,而不是在运行时就像XML一样
  3. 更易于在IDE中导航 – 在bean的构造函数之间来理解依赖关系树。
  4. 可以轻松debuggingconfiguration启动

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

  1. 滥用 – 代码比XML更容易被滥用
  2. 使用XML,您可以根据在编译期间不可用但在运行时提供的类来定义依赖项。 使用@Configuration类时,您必须在编译时提供这些类。 通常这不是问题,但有些情况可能会发生。

底线:在您的应用程序上下文中结合XML, @Configuration Configuration和注释是完全正确的。 Spring不关心bean声明的方法。