Spring @Configuration

本文基于Spring 5.2.7

一、官方文档

org.springframework.context.annotation.Configuration
始自 Spring 3.0
标识一个声明一个或多个@Bean方法的的类,这个类会被Spring容器处理以生成对应的bean definitions和service requests。例子如下:

@Configuration
public class AppConfig {

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

Bootstrapping @Configuration classes

Via  AnnotationConfigApplicationContext

@Configuration类通常被用作启动引导类,通过AnnotationConfigApplicationContext或支持web的变体AnnotationConfigWebApplicationContext,一个简单的使用例子如下:

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

查阅读AnnotationConfigApplicationContext文档获取更多细节,查阅AnnotationConfigWebApplicationContext文档获取有关servlet 容器的web configuration细节。

Via Spring <beans> XML

作为通过AnnotationConfigApplicationContext直接注册@Configuration类的替代,@Configuration类可以在Spring XML文件中被声明为普通的<bean>定义。如下:

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

上面的例子中,需使用<context:annotation-config/>,他能让ConfigurationClassPostProcessor和其他相关注解的post processors工作,用以处理@Configuration类。

Via component scanning

@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;
    }

    // @Bean definition using "SomeBean"

}

@Configuration类不仅仅只被component scanning引导, 而且还能使用@ComponentScan通过自身进行component scanning:

@Configuration
@ComponentScan("com.acme.app.services")
public class AppConfig {
    // various @Bean definitions ...
}

查阅@ComponentScan文档获取更多细节。

Working with externalized values

Using the 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;
    }
}

一个或多个properties文件中的属性被解析到Environment,且@Configuration类能够通过使用@PropertySource注解将properties文件添加到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"));
    }
}

Using the  @Value annotation属性

外部值可以通过使用@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的文档获取更多相关细节)。但是请注意,通过静态@Bean方法显示注册PropertySourcesPlaceholderConfigurer的行为只在需要自定义配置的情况下使用,如自定义占位符语法等。特别地,如果ApplicationContext中没有内置的bean post-processor(例如PropertySourcesPlaceholderConfigurer)被注册,Spring会注册一个默认的解析properties文件的内置解析器到Environment中。

Composing  @Configuration classes

With the @Import annotation

@Configuration类可以通过@Import注解聚合,就像XML中使用<import>一样。因为@Configuration对象是作为Spring beans被管理在Spring容器中的,imported configurations会被注入。例如,通过构造函数注入:

@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());
    }
}

 现在AppConfig和导入的DatabaseConfig能够同时被引导只能在一种情况下发生,那就是AppConfig这样注册:new AnnotationConfigApplicationContext(AppConfig.class)

With the @Profile annotation

@Configuration可以通过指定@Profile注解来表明他们在给定的profile或profiles活动时才被处理。

@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内使用相同效果的变量:

@Configuration
public class ProfileDatabaseConfig {

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

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

With Spring XML using the @ImportResource annotation

如上面提到,@Configuration类可以被声明如同Spring XML中<bean>。可以使用@ImportResource注解引入Spring XML文件到@Configuration类中。从XML中引入的bean definitions可以被注入,通过使用@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);
    }
}

With nested  @Configuration classes

@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();
        }
    }
}

当引导这样的逻辑时,只需针对ApplicationContext注册AppConfig即可。作为嵌套的@Configuration的优势,DatabaseConfig会被自动注册。这避免了当AppConfig和DatabaseConfig之间关系清晰时还使用@Import注解。
同样注意,嵌套@Configuration类能够像@Profile一样在外层@Configuration类提供2种选择的效果。

Configuring lazy initialization

默认情况下,@Bean方法会在容器引导是急加载。为了避免这种情况,@Configuration可以联合@Lazy一起使用,表明@Configuration类里的所有@Bean方法是懒加载的,注意,@Lazy也可以单独用在没有@Bean方法上。

Testing support for {@code @Configuration} classes

spring-test模块中的TestContext framework提供了@ContextConfiguration注解,他能接收component引用数组——典型如@Configuration或@Component类型:

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

    @Autowired MyBean myBean;

    @Autowired DataSource dataSource;

    @Test
    public void test() {
        // assertions against myBean ...
    }
}

Enabling built-in Spring features using @Enable annotations

Spring特性诸如:异步方法执行,定时任务执行,声明事务管理,甚至Spring MVC等,他们都能通过@Configuration类使用各自的@Enable注解开启,查阅@EnableAsync,@EnableScheduling,@EnableTransactionManagement,@EnableAspectJAutoProxy,@EnableWebMvc获取更多细节。

Constraints when authoring @Configuration classes

@Configuration类必须作为类提供(如不能是factory method返回),允许是运行时生成的增强子类。
@Configuration不能是final(因为运行时要通过生成子类增强),除非proxyBeanMethods被设置为false,表明运行时不会生成子类增强。
@Configuration不能是局部类(不能在方法中声明@Configuration类)。
任何嵌套的@Configuration必须是static
@Bean方法不能反过来创建@Configuration类(任何这样的Bean会被当成常规bean对待,他的@Configuration注解也不会被检测到)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值