您的当前位置:首页正文

spring的@Configuration注解

2024-11-30 来源:个人技术集锦

说明

spring的@Configuration注解到类上,用来告诉spring,被注解的类内部声明了一个或多个 @Bean方法,这些@Bean方法可以被Spring容器处理,产生bean的定义以及运行期间对这些bean的业务请求。
例如:

 @Configuration
 public class AppConfig {

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

引导@Configuration类

通过AnnotationConfigApplicationContext引导

@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类。

通过组件扫描(component scanning)引导

因为@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 ...
 }

使用外部的值

使用Environment API

  • 将Spring Environment注入一个@Configuration类,例如使用@Autowired注解注入,然后就可以通过Environment的方法查询外部的值。

示例

 @Configuration
 public class AppConfig {

     @Autowired Environment env;

     @Bean
     public MyBean myBean() {
         MyBean myBean = new MyBean();
         myBean.setName(env.getProperty("bean.name"));
         return myBean;
     }
 }
  • 通过Environment解析的属性可以存在于多个"property source"对象中,@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}") String beanName;

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

这种方法通常跟Spring的PropertySourcesPlaceholderConfigurer一起使用。PropertySourcesPlaceholderConfigurer可以在XML中 通过<context:property-placeholder/> 自动启用、或者在一个@Configuration类中用一个专门的静态@Bean方法来显式启用。注意,通过静态的@Bean方法来显式注册PropertySourcesPlaceholderConfigurer通常在你想要定制一个配置(例如定制一个占位符语法)的时候才需要。

合成@Configuration类

用@Import注解

  • @Configuration类可以通过@Import注解来合成,类似于Spring XML中<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());
     }
 }
  • 现在,通过只对Spring上下文注册AppConfig,即可引导AppConfig和导入的DatabaseConfig:
new AnnotationConfigApplicationContext(AppConfig.class)

用@Profile注解

  • @Configuration类可以用 @Profile注解,表明只有在给定的1个或几个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方法层级声明profile条件,例如在同一个configuration类内部声明替代的bean变体,例如:
 @Configuration
 public class ProfileDatabaseConfig {

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

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

利用@ImportResource注解使用Spring XML

  • 可以使用 @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 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注解。

配置懒初始化(lazy initialization)

默认地,@Bean将在容器引导时被急切地实例化。为了避免这个问题, @Configuration可以和@Lazy注解一起使用,指明在@Configuration类中的所有@Bean方法都会被懒初始化。注意: @Lazy 也可以单独用在 @Bean 方法上。

对@Configuration类的测试支持

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 ...
     }
 }

利用@Enable注解启用内置的spring特性

在 @Configuration中,使用对应的"@Enable"注解,可以启用spring的特性,例如异步方法调用、计划任务执行、注解驱动的事务管理、spring MVC。对应的"@Enable"注解: @EnableAsync, @EnableScheduling, @EnableTransactionManagement, @EnableAspectJAutoProxy, and @EnableWebMvc。

编排@Configuration类的限制

  • Configuration类必须作为一个类提供(即,不是从一个工厂方法返回的实例),这样允许通过一个生成的子类进行运行时增强。
  • Configuration类不能是final的(这样才允许运行时子类),除非proxyBeanMethod标志设置为false,表示不需要运行时的子类。
  • Configuration类不能是局部的(即,不能在一个方法中声明)。
  • 任何嵌套的Configuration类必须声明为static的。
  • @Bean不能再进一步创建Configuration类。
显示全文