Spring Boot 教程

@Configuration 注解

该注解表示一个类声明了一个或多个拥有 @Bean注解的方法,并且这些拥有 @Bean的方法的返回对象将被 Spring 容器管理,在其他类中就可以使用 @Autowired注解注入这些 Bean。例如:

@Configuration
public class AppConfig {
    @Bean
    public MyBean myBean() {
        // instantiate, configure and return bean ...
    }
}

上面配置对应到传统 Spring XML 配置如下:

<bean id=”myBean” class=”com.huangx.springboot.MyBean” />

引导 @Configuration类

通过AnnotationConfigApplicationContext

通常使用AnnotationConfigApplicationContext或其支持Web的变体AnnotationConfigWebApplicationContext来引导 @Configuration 类。AnnotationConfigApplicationContext的一个简单示例如下:

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(AppConfig.class);
ctx.refresh();

MyBean myBean = ctx.getBean(MyBean.class);
// use myBean ...

上面代码通过 AnnotationConfigApplicationContext 手动引导 AppConfig 类。

注意:此时,AppConfig 类上面没有添加 @Configuration 注解

有关更多详细信息,请参见AnnotationConfigApplicationContext 的JavaDocs文档;有关Servlet容器中的Web配置说明,请参见AnnotationConfigWebApplicationContext。

通过Spring <beans> XML

作为直接针对 AnnotationConfigApplicationContext 注册 @Configuration 类的替代方法,可以将 @Configuration 类声明为 Spring XML 文件中的常规 <bean> 定义:

<beans>
   <context:annotation-config/>
   <bean class="com.acme.AppConfig"/>
</beans>

在上面的示例中,需要 <context:annotation-config /> 才能启用 ConfigurationClassPostProcessor 和其他与注释相关的后处理器,这些处理器有助于处理 @Configuration 类。

通过组件扫描

@Configuration 用 @Component 进行元注释,因此 @Configuration 类是组件扫描的候选对象(通常使用Spring XML的 <context:component-scan /> 元素),因此也可以像使用任何普通的 @Component 一样利用 @ Autowired / @ Inject 注解注入。特别是,如果存在单个构造函数,则自动为该构造函数自动应用语义:

@Configuration
public class AppConfig {
    private final SomeBean someBean;

    public AppConfig(SomeBean someBean) {
        this.someBean = someBean;
    }
    // @Bean definition using "SomeBean"
}

@Configuration 类不仅可以使用组件扫描来引导,还可以自己使用 @ComponentScan 注释配置组件扫描:

@Configuration
@ComponentScan("com.acme.app.services")
public class AppConfig {
    // various @Bean definitions ...
}

使用外部化的值

使用Environment API

可以通过将Spring Environment注入@Configuration类中来查找外部化的值。例如,使用 @Autowired 注解:

@Configuration
public class AppConfig {
    @Autowired
	private Environment env;

    @Bean
    public MyBean myBean() {
        MyBean myBean = new MyBean();
        myBean.setName(env.getProperty("bean.name"));
        return myBean;
    }
}

通过 Environment 解析一个或多个属性文件,将属性内容放到 Properties对象中,并且 @Configuration 类可以使用 @PropertySource 注释将属性文件的内容供给 Environment 对象:

@Configuration
@PropertySource("classpath:/com/acme/app.properties")
public class AppConfig {

    @Inject Environment env;

    @Bean
    public MyBean myBean() {
        return new MyBean(env.getProperty("bean.name"));
    }
}

使用@Value注解

可以使用 @Value 注解将外部化的值注入 @Configuration 类:

@Configuration
@PropertySource("classpath:/com/acme/app.properties")
public class AppConfig {
    @Value("${bean.name}") 
    Private String beanName;
    
    @Bean
    public MyBean myBean() {
        return new MyBean(beanName);
    }
}

这种方法通常与Spring的PropertySourcesPlaceholderConfigurer结合使用,可以通过 <context:property-placeholder /> 在XML配置中自动启用它,也可以通过专用的静态 @Bean方法在 @Configuration 类中显式启用它。

但是请注意,通常仅在需要自定义配置(例如占位符语法等)时,才需要通过静态@Bean方法显式注册PropertySourcesPlaceholderConfigurer。

特别是,如果尚未注册任何bean后处理器(例如PropertySourcesPlaceholderConfigurer)作为ApplicationContext的嵌入式值解析器,Spring将注册一个默认的嵌入式值解析器,该解析器根据环境中注册的属性源解析占位符。

组成@Configuration类

使用 @Import 注解

@Configuration 类可以使用 @Import 注释组成,类似于 <import> 在 Spring XML 中的工作方式。因为@Configuration 对象作为容器内的 Spring Bean 管理,所以可以注入导入的配置。例如,通过构造函数注入:

@Configuration
public class DatabaseConfig {
    @Bean
    public DataSource dataSource() {
        // instantiate, configure and return DataSource
    }
}

@Configuration
@Import(DatabaseConfig.class)
public class AppConfig {
    private final DatabaseConfig dataConfig;

    public AppConfig(DatabaseConfig dataConfig) {
        this.dataConfig = dataConfig;
    }

    @Bean
    public MyBean myBean() {
        // reference the dataSource() bean method
        return new MyBean(dataConfig.dataSource());
    }
}

现在,可以通过仅在 Spring 上下文中注册 AppConfig 来引导 AppConfig 和导入的 DatabaseConfig:

new AnnotationConfigApplicationContext(AppConfig.class);

使用@Profile注释

@Configuration 类可以用 @Profile 注释标记,以指示仅当给定的一个或多个配置文件处于活动状态时才应处理它们:

@Profile("development")
@Configuration
public class EmbeddedDatabaseConfig {
    @Bean
    public DataSource dataSource() {
        // instantiate, configure and return embedded DataSource
    }
}

@Profile("production")
@Configuration
public class ProductionDatabaseConfig {
    @Bean
    public DataSource dataSource() {
        // instantiate, configure and return production DataSource
    }
}

另外,您也可以在 @Bean 方法级别声明配置文件条件。例如,对于同一配置类中的替代 bean 变体:

@Configuration
public class ProfileDatabaseConfig {
    @Bean("dataSource")
    @Profile("development")
    public DataSource embeddedDatabase() { ... }

    @Bean("dataSource")
    @Profile("production")
    public DataSource productionDatabase() { ... }
}

使用@ImportResource注释使用Spring XML

如上所述,@ Configuration 类可以在 Spring XML 文件中声明为常规的 Spring  <bean> 定义。也可以使用@ImportResource 注解将 Spring XML 配置文件导入 @Configuration 类。可以注入从 XML 导入的 Bean 定义。例如,使用 @Inject 注解:

@Configuration
@ImportResource("classpath:/com/acme/database-config.xml")
public class AppConfig {
    @Inject DataSource dataSource; // from XML

    @Bean
    public MyBean myBean() {
        // inject the XML-defined dataSource bean
        return new MyBean(this.dataSource);
    }
}

使用嵌套@Configuration类

@Configuration 类可以相互嵌套。如下:

@Configuration
public class AppConfig {
    @Inject
    private DataSource dataSource;

    @Bean
    public MyBean myBean() {
        return new MyBean(dataSource);
    }

    @Configuration
    static class DatabaseConfig {
        @Bean
        DataSource dataSource() {
            return new EmbeddedDatabaseBuilder().build();
        }
    }
}

当引导这种安排时,仅需要针对应用程序上下文注册 AppConfig。由于是嵌套的 @Configuration 类,因此将自动注册DatabaseConfig。当 AppConfig 和 DatabaseConfig 之间的关系已经隐式清除时,这避免了使用@Import注解的需要。还要注意,嵌套的 @Configuration 类可以与 @Profile 注解一起使用,为封闭的 @Configuration 类提供同一 bean 的两个选项。

配置延迟初始化

默认情况下,@Bean 方法将在容器引导时被实例化。为了避免这种情况,可以将 @Configuration 与 @Lazy 注解结合使用,以指示类中声明的所有 @Bean 方法在默认情况下都是延迟初始化的。请注意,@Lazy 也可以用于单个 @Bean 方法。

测试对@Configuration类的支持

spring-test 模块中可用的 SpringTestContext 框架提供了 @ContextConfiguration 注释,它可以接受一个组件类引用数组 —— 通常是 @Configuration 或 @Component 类。例如:

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {AppConfig.class, DatabaseConfig.class})
public class MyTests {
    @Autowired 
    private MyBean myBean;
    
    @Autowired
    private DataSource dataSource;
    
    @Test
    public void test() {
        // assertions against myBean ...
    }
}

使用@Enable注释启用内置的Spring功能

Spring 特性,如异步方法执行、计划任务执行、注释驱动事务管理,甚至 SpringMVC,都可以通过 @Configuration 类使用各自的“@Enable”注释来启用和配置。有关详细信息,请参阅 @EnableAsync、@EnableScheduling、@EnableTransactionManagement、@EnableAspectJAutoProxy 和 @EnableWebMvc。

编写@Configuration类时的约束

  • Configuration类必须作为类提供(即不是从工厂方法返回的实例),允许通过生成的子类运行时增强。

  • Configuration 类必须是非 final 的(允许在运行时提供子类),除非 proxyBeanMethods 标志设置为 false,在这种情况下,不需要运行时生成的子类。

  • Configuration 类必须是非本地的(即不得在方法中声明)。

  • 任何嵌套的配置类都必须声明为静态。

  • @Bean 方法可能不会再创建其他配置类(任何此类实例都将被视为常规Bean,且其配置注释仍未被检测到)。

说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号