了解春季@Configuration课程

2022-08-31 09:01:40

在问题“了解弹簧@Autowired用法”之后,我想为弹簧布线的另一个选项(该类)创建一个完整的知识库。@Configuration

让我们假设我有一个弹簧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

将 XML 迁移到@Configuration

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

  1. 创建带注释的类:@Configuration

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

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

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

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

    @Autowired
    @Qualifier(value = "beanFromSomewhereElse")
    private final StrangeBean beanFromSomewhereElse;
    

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

    @Bean(name = "anotherBean")
    public AnotherClass getAnotherClass(@Qualifier (value = "beanFromSomewhereElse") final StrangeBean beanFromSomewhereElse) {
      return new AnotherClassImpl(getSomeClass(), beanFromSomewhereElse);
    }
    
  5. 导入属性与从另一个 xml 或类导入 Bean 非常相似。我们将不使用,而是按如下方式使用属性:@Configuration@Qualifier@Value

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

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

  6. 为了让 spring 将这些类视为 bean 容器,我们需要通过在上下文中放置此标记来在我们的主 xml 中标记它:

    <context:annotation-config/>
    

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

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

    有一些方法可以完全避免弹簧XML,但它们不在本答案的范围之内。您可以在我的博客文章中找到其中一个选项,我基于此来回答。


使用此方法的优缺点

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

  1. 拼写错误 - 类被编译,拼写错误不允许编译@Configuration
  2. 快速失败(编译时) - 如果您忘记注入Bean,您将在编译时失败,而不是像XML那样在运行时失败
  3. 在 IDE 中更易于导航 - 在 Bean 构造函数之间导航,以了解依赖关系树。
  4. 可以轻松调试配置启动

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

  1. 滥用 - 代码比 XML 更容易被滥用
  2. 使用 XML,您可以基于在编译时不可用但在运行时提供的类来定义依赖项。对于类,您必须在编译时具有可用的类。通常这不是问题,但在某些情况下可能会成为问题。@Configuration

底线:在应用程序上下文中组合 XL 和注释是完全可以的。Spring并不关心豆子的宣布方法。@Configuration


答案 2

推荐