@Configuration

Posted mrray1105

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了@Configuration相关的知识,希望对你有一定的参考价值。

@Configuration全限定名:org.springframework.context.annotation.Configuration

@Target (value =TYPE )
@Retention (value =RUNTIME )
@Documented 
@Component
public @interface Configuration

@Configuration 表示一个类声明了一个或者多个@Bean方法,并且可以由Spring容器处理,以便在运行时为这些bean生成bean定义和服务请求。

@Configuration
 public class AppConfig 

     @Bean
     public MyBean myBean() 
         // 实例化,配置和返回bean...
     
 

 

引导@Configuration类

1 通过AnnotationConfigApplicationContext引导@Configuration类

@Configuration类通常使用AnnotationConfigApplicationContext或其支持Web的变体AnnotationConfigWebApplicationContext进行引导。

简单示例如下:

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

 

2 通过Spring <beans> XM引导@Configuration类

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

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

在上面的示例中,需要<context:annotation-config />以启用ConfigurationClassPostProcessor和其他便于处理@Configuration类的与注解相关的后处理器。

 

3 通过组件扫描的方式引导@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;
     

     // 使用"SomeBean"进行@Bean定义

 

@Configuration类不仅可以使用组件扫描进行引导,还可以使用@ComponentScan注解自行配置组件扫描:

@Configuration
@ComponentScan("com.acme.app.services")
 public class AppConfig 
     // 不同@Bean定义 ...
 

 

使用外部化值

1 通过Environment API使用外部化值

可以通过将Spring 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配置类可以使用@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"));
     
 

 

2 通过@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一起使用,可以通过<context:property-placeholder />在XML配置中自动启用,或者通过专用的静态@Bean方法在@Configuration类中显式启用。 但请注意,通常只有在需要自定义配置(如占位符语法等)时,才需要通过静态@Bean方法显式注册PropertySourcesPlaceholderConfigurer。具体来说,如果没有bean后处理器(例如PropertySourcesPlaceholderConfigurer)为ApplicationContext注册了嵌入值解析器,Spring将注册一个默认的嵌入值解析器,它根据在Environment中注册的属性源来解析占位符。

 

组合@Configuration类

1 通过注解@Import组合@Configuration类

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

@Configuration
 public class DatabaseConfig 

     @Bean
     public DataSource dataSource() 
         // 实例化,配置和返回DataSource
     
 

 @Configuration
 @Import(DatabaseConfig.class)
 public class AppConfig 

     private final DatabaseConfig dataConfig;

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

     @Bean
     public MyBean myBean() 
         // 引用dataSource() bean方法
         return new MyBean(dataConfig.dataSource());
     
 

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

 new AnnotationConfigApplicationContext(AppConfig.class);

 

2 通过@Profile注解组合@Configuration类

@Configuration类可以使用@Profile注解进行标记,以指示只有在给定的配置文件或配置文件处于活动状态时才应处理它们:

 @Profile("development")
 @Configuration
 public class EmbeddedDatabaseConfig 

     @Bean
     public DataSource dataSource() 
         // 实例化,配置和返回嵌入式的DataSource
     
 

 @Profile("production")
 @Configuration
 public class ProductionDatabaseConfig 

     @Bean
     public DataSource dataSource() 
         // 实例化,配置和返回生产用的DataSource
     
 

 或者,您也可以在@Bean方法级别声明profile条件 - 例如,对于同一配置类中的备用bean变体:

 @Configuration
 public class ProfileDatabaseConfig 

     @Bean("dataSource")
     @Profile("development")
     public DataSource embeddedDatabase()  ... 

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

 

3 通过@ImportResource注解使用Spring XML组合@Configuration类

如上所述,@Consfiguration类可以在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; // 来自于XML

     @Bean
     public MyBean myBean() 
         // 注入XML定义的dataSource bean
         return new MyBean(this.dataSource);
     
 

 

4 通过内嵌的@Configuration组合@Configuration类

@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之间的关系已经隐式清除时,这避免了使用@Impor注解的需要。
另请注意,嵌套的@Configuration类可以通过@Profile注解使用,以便为封闭的@Configuration类提供相同bean的两个选项。

 

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


测试对@Configuration类的支持
spring-test模块中提供的Spring TestContext框架提供了@ContextConfiguration注解,它可以接受@Configuration类对象的数组:

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = AppConfig.class, DatabaseConfig.class)
 public class MyTests 

     @Autowired 
     MyBean myBean;

     @Autowired 
     DataSource dataSource;

     @Test
     public void test() 
         // 断言 myBean ...
     
 

 

使用@Enable注解启用内置Spring功能

可以使用各自的“@Enable”注解从@Configuration类启用和配置Spring等功能,例如异步方法执行,计划任务执行,注解驱动事务管理,甚至Spring MVC。例如@EnableAsync,@ EnableScheduling,@ EnableTransactionManagement,@ EnableAspectJAutoProxy和@EnableWebMvc。

 

创作@Configuration类时的约束

必须以类的形式提供配置类(即不是从工厂方法返回的实例),允许通过生成的子类进行运行时增强。
配置类必须是非最终的(non-final)。
配置类必须是非本地的(non-local)(即可能不在方法中声明)。
必须将任何嵌套配置类声明为static。
@Bean方法可能不会反过来创建更多的配置类(任何此类实例都将被视为常规bean,其配置注解仍未被检测到)。

 

备注:

整理翻译自spring-context-5.1.7.RELEASE源码

以上是关于@Configuration的主要内容,如果未能解决你的问题,请参考以下文章