乐趣区

关于java:Configuration注解详解

@Configuration 注解详解

Configuration 代码简介

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

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @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。如果存在单个构造函数,则主动拆卸语义将通明地利用

@Configuration
public 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 注解即可:
@Configuration
public 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 治理,所以导入的配置能够按一般的形式注入(例如,通过构造函数注入):
@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);

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

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

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

@Configuration
public 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 类能够互相嵌套,如下所示:
@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();}
    }
}

当这样疏导时,仅须要针对应用程序上下文注册 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,其配置正文不会被检测到)。
退出移动版