配置-代码
1. 前言
Spring 的代码配置 Java-configuration,核心是通过@Configuration修饰的配置类搭配@Bean修饰的方法来支持的:
The
@Beanannotation is used to indicate that a method instantiates, configures, and initializes a new object to be managed by the Spring IoC container.Annotating a class with
@Configurationindicates that its primary purpose is as a source of bean definitions. Furthermore,@Configurationclasses let inter-bean dependencies be defined by calling other@Beanmethods in the same class.以下两者等价:
代码配置
@Configuration public class AppConfig { @Bean public MyService myService() { return new MyServiceImpl(); } }XML 配置
<beans> <bean id="myService" class="com.acme.services.MyServiceImpl"/> </beans>
When @Configuration classes are provided as input, the @Configuration class itself is registered as a bean definition and all declared @Bean methods within the class are also registered as bean definitions.
When @Component and JSR-330 classes are provided, they are registered as bean definitions, and it is assumed that DI metadata such as @Autowired or @Inject are used within those classes where necessary.
2. Full @Configuration vs lite @Bean mode?
详见 配置-注解:@Configuration vs @Component
3. 构建 IoC 容器
3.1 实例化 IoC 容器——AnnotationConfigApplicationContext
两种方式。
In much the same way that Spring XML files are used as input when instantiating a ClassPathXmlApplicationContext, you can use @Configuration classes as input when instantiating an AnnotationConfigApplicationContext.
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
MyService myService = ctx.getBean(MyService.class);
myService.doStuff();
}You can instantiate an AnnotationConfigApplicationContext by using a no-arg constructor and then configure it by using the register() method.
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(AppConfig.class, OtherConfig.class);
ctx.register(AdditionalConfig.class);
ctx.refresh();
MyService myService = ctx.getBean(MyService.class);
myService.doStuff();
}3.2 设置包扫描路径
除了在 @Configuration 配置类上使用 @ComponentScan 注解外,也可以使用 AnnotationConfigApplicationContext 暴露的scan(String...)方法。以下两种方式等价:
注解:
@Configuration @ComponentScan(basePackages = "com.acme") public class AppConfig { // ... }scan 方法:
public static void main(String[] args) { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); ctx.scan("com.acme"); ctx.refresh(); MyService myService = ctx.getBean(MyService.class); }Remember that
@Configurationclasses are meta-annotated with@Component, so they are candidates for component-scanning.In the preceding example, assuming that
AppConfigis declared within thecom.acmepackage (or any package underneath), it is picked up during the call toscan(). Uponrefresh(), all its@Beanmethods are processed and registered as bean definitions within the container.
3.3 AnnotationConfigWebApplicationContext
A WebApplicationContext variant of AnnotationConfigApplicationContext is available with AnnotationConfigWebApplicationContext. You can use this implementation when configuring the Spring ContextLoaderListener servlet listener, Spring MVC DispatcherServlet, and so forth.
4. @Profile, @Conditional
It is often useful to conditionally enable or disable a complete @Configuration class or even individual @Bean methods, based on some arbitrary system state.
One common example of this is to use the @Profile annotation to activate beans only when a specific profile has been enabled in the Spring Environment (see Bean Definition Profiles for details).
The @Profile annotation is actually implemented by using a much more flexible annotation called @Conditional. The @Conditional annotation indicates specific org.springframework.context.annotation.Condition implementations that should be consulted before a @Bean is registered.
package org.springframework.context.annotation;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional({ProfileCondition.class})
public @interface Profile {
String[] value();
}package org.springframework.context.annotation;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
Class<? extends Condition>[] value();
}