前言
Spring所依赖的两个核心理念,一个是控制反转(IoC),另一个是面向切面编程(AOP),IoC是Spring的核心。
IoC是一种通过描述来生成或者获取对象的技术,在Spring中把每一个需要管理的对象成为Spring Bean,管理这些Bean的容器,被我们称为Spring IoC容器,IoC容器需要具备以下两个特点:
- 通过描述管理Bean,包括发布和获取。
- 通过描述完成Bean之间的依赖关系。
IoC容器简介【Spring 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的生命周期 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 自定义销毁方法
- value 定义容器中Bean的名称,如果没有配置,默认使用类名首字母小写作为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注解。
- required 如果不能确定注解标注属性一定存在并且允许这个属性为null的时候,可以将该值配置为 false
注意:当多个相同类型的Bean同时标注了@Primary,@Autowired仍会抛出异常。
@Qualifier 与@Autowired一同使用
- value 指定注入的Bean的名称
推荐阅读
- Spring认证中国教育管理中心-Spring Data Elasticsearch教程二
- 微服务注册中心
- 谈谈我自己理解的Spring为什么一定要用三级缓存
- (为什么在 Spring 的配置里,最好不要配置 xsd 文件的版本号)