Spring 容器配置

基于注解的容器配置

  • @Autowired :自动注入,可设置在字段(支持数组和集合)、构造函数、setter 方法、任意名称的多个参数的方法上

  • @Primary: 指定优先注入候选者

  • @Qualifier:明确指定注入候选者,与 @Autowired 一起使用

  • @Resource:通过 name 指定注入候选者,可设置在字段(支持数组和集合)、单参数的 setter 方法上

  • @Value

  • @PostConstruct@PreDestroy

本质上都是基于容器扩展点实现,如:

  • ConfigurationClassPostProcessor (BeanFactoryPostProcessor)

  • AutowiredAnnotationBeanPostProcessor (BeanPostProcessor)

  • CommonAnnotationBeanPostProcessor (BeanPostProcessor)

  • PersistenceAnnotationBeanPostProcessor(BeanPostProcessor)

  • EventListenerMethodProcessor(BeanFactoryPostProcessor)

基于Java的容器配置

使用AnnotationConfigApplicationContext即可支持@Bean@Configuration 进行容器配置。

小心

默认情况下,使用 Java 配置定义的具有公共 close 或 shutdown 方法的 bean 会自动注册销毁回调。如果您有公共 close 或 shutdown 方法, 并且您不希望在容器关闭时调用它,则可以将 @Bean(destroyMethod = “”) 添加到您的 bean定义禁用默认的 (inferred) 模式。

可以使用@Import从另一个配置类加载 @Bean 定义,类似于 AnnotationConfigApplicationContext.register 方法

@Configuration
@Import(ConfigA.class)
public class ConfigB {

	@Bean
	public B b() {
		return new B();
	}
}

通过@Profile可以实现有条件地包含 @Configuration 类或 @Bean 方法, 仅当 Spring Environment 中启用了特定配置文件时才使用 @Profile 注释来激活 Bean。 @Profile 实际上是通过使用更灵活的注释 @Conditional 来实现的

Classpath 扫描和 Components 管理

@Component 是元注解,@Repository 、 @Service 和 @Controller 是使用 @Component 标记的注解。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component 
public @interface Service {

	// ...
}

常规 Spring 组件中的 @Bean 方法的处理方式与 Spring @Configuration 类中对应方法的处理方式不同。 @Configuration 类在启动时都使用 CGLIB 进行子类化。在子类中,子方法在调用父方法并创建新实例之前, 首先检查容器中是否有任何缓存(作用域)bean,因此可以正确处理 bean 之间的依赖关系。

// @Component
@Configuration
public class AppConfig {

	@Bean
	public ClientService clientService1() {
		ClientServiceImpl clientService = new ClientServiceImpl();
		clientService.setClientDao(clientDao());
		return clientService;
	}

	@Bean
	public ClientService clientService2() {
		ClientServiceImpl clientService = new ClientServiceImpl();
		clientService.setClientDao(clientDao());
		return clientService;
	}

	@Bean
	public ClientDao clientDao() {
		return new ClientDaoImpl();
	}
}