前言

Spring所依赖的两个核心理念,一个是控制反转(IoC),另一个是面向切面编程(AOP),IoC是Spring的核心。
IoC是一种通过描述来生成或者获取对象的技术,在Spring中把每一个需要管理的对象成为Spring Bean,管理这些Bean的容器,被我们称为Spring IoC容器,IoC容器需要具备以下两个特点:

  • 通过描述管理Bean,包括发布和获取。
  • 通过描述完成Bean之间的依赖关系。

    IoC容器简介

    Spring IoC容器是一个管理Bean的容器,在Spring的定义中,所有的IoC容器都必须实现接口 BeanFactory,它是一个顶级的容器接口。
    BeanFactory 接口中定义了多个 getBean 方法,它们的意义就是在容器中获取Bean,其中允许我们按照类型或是名称来获取指定的Bean。
    默认情况下,Bean在容器中都是以单例存在的
    由于 BeanFactory 接口还不够强大,于是Spring开发了一个更高级的接口 ApplicationContext,它是 BeanFactory 的子接口之一,它在 BeanFactory 的基础上扩展了消息国际化接口(MessageSource)、环境可配置接口(EnvironmentCapable)、应用事件发布接口(ApplicationEventPublisher)和资源模式解析接口(ResourcePatternResolver), 所以它的功能更加强大。
    Spring为我们实现了许多IoC容器,这里主要介绍基于注解的容器 AnnotationConfigApplicationContext

依赖注入

Bean之间的依赖关系,Spring的容器概念中,称之为依赖注入。

Bean的生命周期

Bean的生命周期大致上分为,Bean的定义,Bean的初始化,Bean的生存期和Bean的销毁。
Bean的定义的流程如下:

graph TD
R1[例如ComponentScan注解所定义的扫描包]
R2[将Bean的定义保存到BeanDefinition的实例中]
R3[IoC容器装载Bean定义]
F1[资源定位]
F2[Bean定义]
F3[发布Bean定义]
R1 -.-> F1
R2 -.-> F2
R3 -.-> F3
F1 --> F2
F2 --> F3

Bean的之后三个流程的流程如下:

graph TD
R1([接口BeanNameAware])
R2([接口BeanFactoryAware])
R3([接口ApplicationContextAware - 需要容器实现ApplicationContext接口才会被调用])
R4([接口BeanPostProcessor的预初始化方法 - 针对全部Bean生效])
R5([PostConstruct注解标注的方法])
R6([接口InitializingBean])
R7([接口BeanPostProcessor的后初始化方法 - 针对全部Bean生效])
R8([PostConstruct注解标注的方法])
R9([接口DisposableBean])
F1[初始化]
F2[依赖注入]
F3[setBeanName方法]
F4[setBeanFactory方法]
F5[setAppliationContext方法]
F6[postProcessBeforeInitialization方法]
F7[自定义初始化方法]
F8[afterPropertiesSet方法]
F9[postProcessAfterInitialization方法]
F10{生存期}
F11[自定义销毁方法]
F12[destory方法]

F1 --> F2 ---> F3
R1 -.-> F3
F3 ---> F4
R2 -.-> F4 ---> F5
R3 -.-> F5
F5 ---> F6
R4 -.-> F6
F6 ---> F7
R5 -.-> F7
F7 ---> F8
R6 -.-> F8
F8 ---> F9
R7 -.-> F9
F9 ---> F10 --> F11
R8 -.-> F11
F11 ---> F12
R9 -.-> F12

注解解析

@Configuration 代表被注解标记的类是一个Java的配置文件。

@Bean 代表被注解标记的方法返回的POJO装配到容器中。

  • name 定义容器中Bean的名称,如果没有配置,默认使用方法名作为Bean的名称。
  • initMethod 自定义初始化方法
  • destroyMethod 自定义销毁方法

@Component 代表被注解标记的类被装配到容器中

  • value 定义容器中Bean的名称,如果没有配置,默认使用类名首字母小写作为Bean的名称。

@ComponentScan 表明采用何种策略去装配Bean,该注解默认的扫描路径为标注注解的类所在包以及其子包

  • basePackages 指定需要扫描的包,可以使用正则表达式。
  • basePackageClasses 指定需要扫描的类。
  • includeFilters 满足过滤条件的Bean才扫描。
  • excludeFilters 排除过滤条件的Bean才扫描。
  • lazyInit 延迟初始化,默认为false

    @ComponentScan(basePackages = "com.springboot.xx.*",
      excludeFilters = {@Filter(classes = {UserService.class})})
    // 该示例中,指定扫描com.springboot.xx下面的所有包,而排除了UserService的装配,即时该类标注了创建Bean的注解,Spring也不会将其装配到容器中。

    @SpringBootApplication 注解中也添加了@ComponentScan注解,我们可以使用它提供的 scanBasePackages scanBasePackageClasses 来配置扫描路径,其外,它还提供了 exclude excludeName 来通过名称或类型来排除自动配置类,如果这些属性满足不了你对装配的需求,可以额外使用@ComponentScan注解。

@Autowired 依赖注入注解,会根据类型找到对应的Bean进行注入,如果寻找的Bean不是唯一的,那么它会根据其属性名称和Bean的名称进行匹配,如果匹配成功,则使用该Bean,如果仍无法匹配,则抛出异常。该注解是一个默认必须找到对应Bean的注解。

  • required 如果不能确定注解标注属性一定存在并且允许这个属性为null的时候,可以将该值配置为 false

@Primary 装配优先权注解,当@Autowired找到两个相同类型的Bean时,会优先使用被@Primary标注的Bean,而不是抛出异常。
注意:当多个相同类型的Bean同时标注了@Primary,@Autowired仍会抛出异常。

@Qualifier 与@Autowired一同使用

  • value 指定注入的Bean的名称

冇妹
12 声望2 粉丝

重峦叠嶂,庆幸相逢。