Spring(一)--SpringBeanIOC的依赖注入

依赖注入的模式与类型

  • 手动模式: 1.XML,Java注解配置元信息,API配置元信息
  • 自动模式: Autowring,即不需要任何配置就能自动注入(根据名字或类型等)

Spring(一)--SpringBeanIOC的依赖注入

为什么自动模式不被推荐

  • 根据名称来自动注入,一旦变量名改了,就无法生效。
  • 对于基本类型,比如int,String等,也无法使用自动绑定

Setter方法依赖注入

  • XML资源配置元信息,其实是setter注入
  • Java注解配置元信息
  • API配置元信息:
BeanDefinitionBuilder definitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(UserHolder.class);
// 设置user属性指向superUser这个Bean
definitionBuilder.addPropertyReference("user", "superUser");
BeanDefinition userHolderBeanDefinition = definitionBuilder.getBeanDefinition();
// 将BeanDefinition注入applicationContext中
applicationContext.registerBeanDefinition("userHolder", userHolderBeanDefinition);
// 刷新容器,使得bean被生成
applicationContext.refresh();

构造器注入

  • XML资源配置元信息,
  • Java注解配置元信息
  • API配置元信息
BeanDefinitionBuilder definitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(UserHolder.class)
// 定义构造器参数
definitionBuilder.addConstructorArgReference("superUser");
return definitionBuilder.getBeanDefinition();

字段注入

字段注入指的是直接对字段操作,而不是对方法或构造器

  • Java注解配置元信息: @Autowried , @Resource , @Inject

方法注入

  • Java配置元信息: @Autowired, @Resource , @Inject @Bean

接口回调注入

Spring(一)--SpringBeanIOC的依赖注入

限定注入

  • 使用注解 @Qualifier 限定

1.通过Bean名称限定,在待注入字段上加 @Qualifier('service1') 这个就限定了Bean名称
2.通过分组限定,在@Bean方法上加上@Qualifier,则该Bean被分到了@Qualifier组,如果要扩展组,则自定义注解派生@Qualifier,比如@LoadBalance。被@LoadBalance注解的bean,也能被@Qualifier限定注入,而@Autowired属于没有组,不会注入被分了组的Bean

@Bean
@Qualifier
public User user() {
    return new User()
}

@Autowired
// 这里不会注入上面那个bean,因为user Bean已经被分组了
private User user;

延迟依赖注入

  • 使用API ObjectFactroy延迟注入
  • 使用API ObjectProvider延迟注入(推荐)
@Autowired
private ObjectProvider<User> objectProvider;

依赖处理过程

  • 入口-DefaultListableBeanFactory#resolveDependency
  • 依赖描述符-DependencyDescriptor
  • 自定绑定候选对象处理器-AutowireCandidateResolver

@Autowired 注入

  • 元信息解析,AutowiredAnnotationBeanPostProcessor类postProcessMergedBeanDefinition处理元数据
  • 依赖查找,AutowiredAnnotationBeanPostProcessor类postProcessProperties进行依赖注入及查找
  • 依赖注入(字段、方法)

@Inject 注入

  • 如果JSR-330存在于ClassPath中,复用AutowiredAnnotationBeanPostProcessor实现
public AutowiredAnnotationBeanPostProcessor() {
    this.autowiredAnnotationTypes.add(Autowired.class);
    this.autowiredAnnotationTypes.add(Value.class);
    try {
        this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
                                          ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
        logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
    }
    catch (ClassNotFoundException ex) {
        // JSR-330 API not available - simply skip.
    }
}

Java通用注解注入原理

  • CommonAnnotationBeanPostProcessor处理下面常见的注解
@Resource
@PostConstruct
@PreDestroy

自定义依赖注入注解

  • 基于AutowiredAnnotationBeanPostProcessor实现
  • 自定义实现, 生命周期处理: InstantiationAwareBeanPostProcessor,MergedBeanDefinitionPostProcessor。元数据,InjectedElement,InjectionMetadata用于存储元数据信息。
上一篇:大数据最难源码 hbase 阅读(一)


下一篇:Spring深入浅出(十),注解,@Qualifier