spring的@Configuration注解到类上,用来告诉spring,被注解的类内部声明了一个或多个 @Bean方法,这些@Bean方法可以被Spring容器处理,产生bean的定义以及运行期间对这些bean的业务请求。
例如:
@Configuration
public class AppConfig {
@Bean
public MyBean myBean() {
// instantiate, configure and return bean ...
}
}
@Configuration类通常通过 AnnotationConfigApplicationContext或者它的web环境下的变种AnnotationConfigWebApplicationContext.进行引导。
例如:
@Configuration
public class AppConfig {
@Bean
public MyBean myBean() {
// instantiate, configure and return bean ...
}
}
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(AppConfig.class);
ctx.refresh();
MyBean myBean = ctx.getBean(MyBean.class);
// use myBean ..
Spring <beans> XML
引导作为通过AnnotationConfigApplicationContext引导 @Configuration类的一个替代方案,可以通过Spring XML文件中定义一个正常的<bean>
。
例如:
<beans>
<context:annotation-config/>
<bean class="com.acme.AppConfig"/>
</beans>
在上面的例子中,需要使用<context:annotation-config/>
,目的是启用ConfigurationClassPostProcessor和其它注解相关的post processors,方便处理@Configuration类。
因为@Configuration 又被 @Component注解,所以被@Configuration注解的类是组件扫描的候选对象。组件扫描可以通过@ComponentScan注解或者XML的 <context:component-scan/>
元素,也可以利用@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 ...
}
示例:
@Configuration
public class AppConfig {
@Autowired Environment env;
@Bean
public MyBean myBean() {
MyBean myBean = new MyBean();
myBean.setName(env.getProperty("bean.name"));
return myBean;
}
}
@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}") String beanName;
@Bean
public MyBean myBean() {
return new MyBean(beanName);
}
}
这种方法通常跟Spring的PropertySourcesPlaceholderConfigurer一起使用。PropertySourcesPlaceholderConfigurer可以在XML中 通过<context:property-placeholder/>
自动启用、或者在一个@Configuration类中用一个专门的静态@Bean方法来显式启用。注意,通过静态的@Bean方法来显式注册PropertySourcesPlaceholderConfigurer通常在你想要定制一个配置(例如定制一个占位符语法)的时候才需要。
<import>
的方式。因为@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());
}
}
new AnnotationConfigApplicationContext(AppConfig.class)
例如:
@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
}
}
@Configuration
public class ProfileDatabaseConfig {
@Bean("dataSource")
@Profile("development")
public DataSource embeddedDatabase() { ... }
@Bean("dataSource")
@Profile("production")
public DataSource productionDatabase() { ... }
}
@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
public class AppConfig {
@Inject DataSource dataSource;
@Bean
public MyBean myBean() {
return new MyBean(dataSource);
}
@Configuration
static class DatabaseConfig {
@Bean
DataSource dataSource() {
return new EmbeddedDatabaseBuilder().build();
}
}
}
当引导这样的嵌套@Configuration类时,只有AppConfig需要注册到应用上下文中, DatabaseConfig将会被自动注册。当AppConfig 和DatabaseConfig 的关系已经隐含着非常清晰时,这种嵌套就避免了使用一个@Import注解。
默认地,@Bean将在容器引导时被急切地实例化。为了避免这个问题, @Configuration可以和@Lazy注解一起使用,指明在@Configuration类中的所有@Bean方法都会被懒初始化。注意: @Lazy 也可以单独用在 @Bean 方法上。
Spring TestContext框架提供了@ContextConfiguratio注解,该注解可以接受组件类引用的数组,通常是 @Configuration类或@Component类。
例如:
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = {AppConfig.class, DatabaseConfig.class})
class MyTests {
@Autowired MyBean myBean;
@Autowired DataSource dataSource;
@Test
void test() {
// assertions against myBean ...
}
}
在 @Configuration中,使用对应的"@Enable"注解,可以启用spring的特性,例如异步方法调用、计划任务执行、注解驱动的事务管理、spring MVC。对应的"@Enable"注解: @EnableAsync, @EnableScheduling, @EnableTransactionManagement, @EnableAspectJAutoProxy, and @EnableWebMvc。