@Configuration注解详解

Configuration代码简介

Configuration正文类表明其次要目标是作为bean定义的源;@Configuration类容许通过调用同一类中的其余@Bean办法来定义bean之间的依赖关系

@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Componentpublic @interface Configuration {   String value() default "";}

一个类申明一个或多个 @Bean办法,并且能够由Spring容器进行解决,以在运行时为这些bean生成bean定义和服务申请,例如:

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

@Configuration 类通应用 AnnotationConfigApplicationContext或具备Web性能的org.springframework.web.context.support.AnnotationConfigWebApplicationContext AnnotationConfigWebApplicationContext进行疏导,如下

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();ctx.register(AppConfig.class);ctx.refresh();MyBean myBean = ctx.getBean(MyBean.class);// use myBean ...

间接在AnnotationConfigApplicationContext上注册 @Configuration类的代替办法,能够在Spring的XML文件中将 @Configuration类申明为一般<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 或者javax.inject.Inject @Inject。如果存在单个构造函数,则主动拆卸语义将通明地利用

@Configurationpublic class AppConfig {    private final SomeBean someBean;    public AppConfig(SomeBean someBean) {        this.someBean = someBean;    }    // @Bean definition using "SomeBean"}
@Configuration技巧
  • 能够通过将Spring的org.springframework.core.env.Environment注入@Configuration类中须要的外部环境值;例如,应用 @Autowired 注解即可:
@Configurationpublic class AppConfig {    @Autowired Environment env;    @Bean    public MyBean myBean() {        MyBean myBean = new MyBean();        myBean.setName(env.getProperty("bean.name"));        return myBean;    }}
  • Environment解析的属性驻留在一个或多个“属性源”对象, @Configuration 能够应用 org.springframework.core.env.PropertySources @PropertySources注解:
@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将内部化的值连贯到 @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的 org.springframework.context.support.PropertySourcesPlaceholderConfigurer
PropertySourcesPlaceholderConfigurer, 通常用<context:property-placeholder />的XML开启。

  • @Configuration 类能够应用@Import注解组成,与 <import>在Spring XML中的工作形式不同。 @Configuration 对象作为容器内的Spring bean治理,所以导入的配置能够按一般的形式注入(例如,通过构造函数注入):
@Configurationpublic 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);

@Configuration 类能够用 @Profile注解进行标记,以批示仅当给定的一个或多个配置文件为 active时才应答其进行解决

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

另外,也能够在 @Bean办法级别,例如 申明配置文件条件。对于同一配置类中的代替bean变体:

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

如上所述,在XML文件中,能够将 @Configuratio}类申明为惯例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类能够互相嵌套,如下所示:
@Configurationpublic class AppConfig {    @Inject 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办法上应用。

  • spring-test模块中的Spring的TestContext框架提供了 @ContextConfiguration注解,从Spring 3.1开始,该注解能够承受 @Configuration的数组类对象:
@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(classes={AppConfig.class, DatabaseConfig.class})public class MyTests {    @Autowired MyBean myBean;    @Autowired DataSource dataSource;    @Test    public void test() {        // assertions against myBean ...    }}

应用 @Enable注解启用内置的Spring性能,比方异步办法执行,定时工作执行,正文驱动的事务管理和SpringMVC类的Spring性能都能够启用和通过@Configuration类进行配置应用各自的“ @Enable”正文。
比方

org.springframework.scheduling.annotation.EnableAsync,@EnableAsync
org.springframework.scheduling.annotation.EnableScheduling @EnableScheduling,
org.springframework.transaction.annotation.EnableTransactionManagement @EnableTransactionManagement
org.springframework.context.annotation.EnableAspectJAutoProxy @EnableAspectJAutoProxy,
rg.springframework.web.servlet.config.annotation.EnableWebMvc @EnableWebMvc

@Configuration的束缚
  1. Configuration类必须作为类提供(即不作为从工厂办法返回的实例),以容许通过生成的子类加强运行时
  2. 配置类必须不是final。
  3. 配置类必须是非本地的(即,不能在办法中申明)。
  4. 任何嵌套的配置类都必须申明为static。
  5. @Bean 办法不会再创立其余配置类(任何此类实例都将被视为惯例Bean,其配置正文不会被检测到)。