spring
官方文档:spring
目录
IOC
IOC也称DI,IOC所提供的功能是由DI来实现的,可以认为它们是对同一个概念的不同角度的描述;
控制反转(IOC):将设计好的对象交给容器控制,而不是在对象内部直接控制;
依赖注入(DI):组件之间的依赖关系由容器在运行期决定;
容器加载
IOC加载过程(以AnnotationConfigApplicationContext注解扫描容器作为入口说明,容器的顶层接口是BeanFactory):
创建容器对象:在创建容器的过程会创建这些对象:
PathMatchingResourcePatternResolver:用于解析类路径或者文件系统中的资源文件;DefaultListableBeanFactory:也是一个容器,实现了BeanDefinitionRegistry、BeanFactory等接口;AnnotatedBeanDefinitionReader:解析class为bean定义,用于扫描class下的bean定义;ClassPathBeanDefinitionScanner:功能同上一个,用于扫描包下的bean定义;
注册bean定义:调用容器的register方法注册bean定义,实际就是调用上边AnnotatedBeanDefinitionReader对象的register方法,具体过程如下:
- 注册bean定义的过程中会解析
Lazy、Primary、DependsOn、Role、Description等注解信息并保存到AnnotatedBeanDefinition对象中; - 将解析到的bean定义信息保存到
BeanDefinitionHolder - 判断
ScopedProxyMode - 注册bean定义到容器中(
registerBeanDefinition方法注册);- 校验bean定义;
- 判断容器中是否已有这个bean定义,如果有的话,根据allowBeanDefinitionOverriding配置确实覆盖bean定义还是抛异常;
- 获取并保存bean定义的别名
刷新容器:调用容器的refresh方法刷新容器,这个方法是整个容器加载的核心方法,大致流程如下:
- 使用
synchronized对整个方法加锁; - 容器预处理,包含设置开始时间、容器状态、初始化配置的钩子方法、校验environment配置、初始化监听器容器(就是个空Set);
- 获取BeanFactory,就是上面创建容器时创建的
DefaultListableBeanFactory; - 预处理BeanFactory,主要设置一些参数,具体在[这里](# beanFactory预处理);
- 预处理BeanFactory后置处理器:一个空的钩子函数;
- 执行BeanFactory后置处理器:
BeanFactoryPostProcessor,这一步会将大量的bean定义加入到容器中,具体流程看[这里](# BeanFactory后置处理器); - 注册Bean后置处理器:
BeanPostProcessor,注册过程在[这里](# Bean后置处理器) - 初始化messageSource:如果容器中有,则从容器中获取,如果没有,则创建
DelegatingMessageSource,并放到容器中,用于国际化处理; - 初始化事件分发器;
- 执行空的钩子方法
onRefresh;springboot中就是扩展的这个方法启动web容器; - 注册监听器;
- 实例化所有非懒加载的单实例bean,创建Bean的核心方法,在[这里](# Bean实例化);
- 发布相应的事件;
- 清除容器加载过程中的缓存信息,主要时反射元数据缓存;
beanFactory
功能说明
spring容器在创建容器对象时会创建一个beanFactory内置在容器中,本文是DefaultListableBeanFactory,这个保存bean定义、注册并执行后置处理器等很多地方都有用到;
beanFactory预处理
beanFactory预处理内容:
- 类加载器;
- 表达式解析器(spel);
- 属性配置编辑器注册器:
ResourceEditorRegistrar - 后置处理器:
ApplicationContextAwareProcessor、ApplicationListenerDetector、LoadTimeWeaverAwareProcessor; - 忽略的Aware接口:
EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware - 可用于解析的自动装配:
BeanFactory、ResourceLoader、ApplicationEventPublisher、ApplicationContext; - 配置信息等;
BeanFactory后置处理器
执行流程
BeanFactory后置处理器执行流程如下(这里的beanFactory就是容器创建时创建的容器):
- 获取容器对象中设置的beanFactoryPostProcessors作为入参;
- 判断beanFactory是否实现了BeanDefinitionRegistry接口(这里都是实现了的);
- 先处理入参的后置处理器,找到实现了
BeanDefinitionRegistryPostProcessor接口的后置处理器,执行postProcessBeanDefinitionRegistry方法; - 再处理容器中的后置处理器;
- 先通过
beanFactory.getBeanNamesForType方法获取所有实现了BeanDefinitionRegistryPostProcessor接口的bean名称 - 从这些后置处理器的bean中找到实现了
PriorityOrdered接口的处理器,排序后依次执行postProcessBeanDefinitionRegistry方法;(这里有一个重要的后置处理器ConfigurationClassPostProcessor,业务中常用的@ComponentScan、@PropertySources、@Configuration、@Bean、@Component、@Import等注解就是在这里添加到beanDefinition中的,主要实现逻辑在:org.springframework.context.annotation.ConfigurationClassParser#doProcessConfigurationClass) - 按上一步的逻辑处理实现了
Ordered接口的后置处理器 - 再对剩下的
BeanDefinitionRegistryPostProcessor进行类似的排序并执行; - 然后执行上面这些后置处理器的
postProcessBeanFactory方法; - 从beanFactory中获取所有实现了
BeanFactoryPostProcessor接口的bean; - 剔除掉上面已经执行过的
BeanDefinitionRegistryPostProcessor; - 按上面类似的逻辑对这些后置处理器,分为实现了
PriorityOrdered接口的、实现了Ordered接口的和没有实现排序接口的三个list; - 对这三个list依次排序并执行
postProcessBeanFactory方法; - 最后清理临时变量,执行结束;
小结
spring5.2.x中顶层的BeanFactoryPostProcessor接口有两个:
BeanFactoryPostProcessor:在bean定义注册之后,bean创建之前执行,具体在上面的源码步骤分析中有;
接口定义,该接口有一个抽象方法,参数就是上面的BeanFactory,可以在这个方法中完成对Bean定义的修改以及属性的修改等,例如CustomAutowireConfigurer就是通过这个接口添加@Qualifier注解功能的,另外,强烈不建议在这里实例化bean,如果需要实例Bean,可以在BeanPostProcessor中完成:
@FunctionalInterface
public interface BeanFactoryPostProcessor {
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
BeanDefinitionRegistryPostProcessor:这个接口继承BeanFactoryPostProcessor,也具有相应功能,其继承方法优先执行,同时它自身的抽象方法会在postProcessBeanFactory方法之前执行;
接口定义,参数是BeanDefinitionRegistry,可以完成对bean定义的增删改查,上面提到过ConfigurationClassPostProcessor就是通过这个方法完成Bean定义的扫描的:
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
Bean实例化
在spring容器中,单实例的非懒加载的bean的创建过程如下:
- 设置值解析器 —— 用于解析配置文件;
- 初始化LoadTimeWeaverAware;
- 设置参数(临时类加载器、允许缓存bean定义元数据);
- 遍历bean名称,执行后续步骤;
- 获取bean定义;
- 判断bean:不是抽象类、是单实例、不是懒加载、不是FactoryBean;
- 满足条件则调用
getBean方法继续创建bean; - 如果是FactoryBean,则工厂bean名称前加
&,原bean名称代表工厂bean返回的bean;
- 满足条件则调用
- 调用
getBean方法开始获取bean - 解析bean名称 —— 处理有别名的情况;
- 尝试获取bean,获取到则直接返回这个bean,否则继续;
- 尝试从一级缓存获取bean(一级缓存实际就是个
ConcurrentHashMap) - 如果获取失败并且bean正在创建中,则尝试从二级缓存获取(是一个HashMap);
- 如果又获取失败并且允许提前引用,则尝试从三级缓存获取(也是一个HashMap)—— 三个缓存是个ObjectFactory,在获取bean时会先执行后置处理器的
getEarlyBeanReference方法,给后置处理器一个增强bean的机会;然后添加到二级缓存,然后将三级缓存的这个bean清除;
- 尝试从一级缓存获取bean(一级缓存实际就是个
- 如果获取失败,则检查bean是否正在创建,如果是则代表有循环依赖,抛出异常,否则继续创建;
- 检查bean定义是否存在父工厂中,如果是则调用父工厂的getBean方法,若不是则继续;
- 标记bean正在创建中;
- 获取并检查bean定义;
- 获取dependsOn,如果有,先检查如果有循环依赖,则抛出异常,否则对依赖的bean调用getBean方法;
- 判断是否单例bean,这里只讨论单例bean的情况,即调用getSingleton方法获取或创建bean;
- 加锁
- 尝试从一级缓存获取,成功则返回,否则继续
- 判断容器状态,如果已被销毁则抛异常;
- 如果是循环创建,则抛异常,否则继续;
- 调用入参对象ObjectFactory的
getObject方法(入参是个lambda表达式,它是通过调用createBean方法创建bean,这个方法在后面单独分析)获取或者创建bean; - 去掉bean创建中的标记
- 将bean从二、三级缓存中删除并添加到一级缓存,同时添加到已注册的bean列表中;
- 判断是否FactoryBean,如果是最终会调用
getObject方法获取bean,否则直接返回当前bean; - 到此,一个bean就创建完成,可以开始创建下一个bean了;
- 再遍历一次bean:判断是否实现了
SmartInitializingSingleton接口,若是则执行afterSingletonsInstantiated方法 - 到此,单实例非懒加载的bean就创建完成了;
这里再简单分析下创建bean的方法的大概流程:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[]):
- 解析并检查bean定义;
- 遍历所有的
BeanPostProcessor - 如果找到
InstantiationAwareBeanPostProcessor后置处理器,则执行postProcessBeforeInstantiation方法; - 如果后置处理器方法返回值不为空,则直接返回后置处理器返回的对象,然后继续遍历
BeanPostProcessor执行postProcessAfterInitialization,改方法返回值作为最终bean返回 —— 相当于该方式创建的bean不需要在初始化了;否则继续调用doCreateBean方法创建bean,后面的步骤都是在这个方法中实现的; - 检查是否是public的bean;
- 检查instanceSupplier、getFactoryMethodName等;
- 判断是否有
SmartInstantiationAwareBeanPostProcessor后置处理器,如果有则执行determineCandidateConstructors方法获取构造器 - 如果找到了构造器会设置解析构造参数赋值然后创建对象,这里不深入讨论,如果没有找到合适的构造器,则继续调用instantiate方法实例化对象;
- instantiate方法中,会判断bean中是否有覆盖方法(即是否有实现接口):
- 没有:通过Class对象获取构造方法,然后通过
BeanUtils.instantiateClass方法实例化对象; - 有:通过
CglibSubclassCreator静态内部类创建cglib代理对象;
- 没有:通过Class对象获取构造方法,然后通过
- 将创建好的对象包装到
BeanWrapper对象中 - 遍历找到
MergedBeanDefinitionPostProcessor后置处理器,执行postProcessMergedBeanDefinition方法 - 将bean封装到
ObjectFactory(重写getObject方法,使用getEarlyBeanReference方法封装,使得在获取bean之前会执行SmartInstantiationAwareBeanPostProcessor后置处理器的getEarlyBeanReference方法,AOP代理就是利用这个方法解决循环依赖下的增强对象),并添加到三级缓存,将bean名称添加注册表; - 后面开始初始化bean;
- 获取
InstantiationAwareBeanPostProcessor后置处理器并执行postProcessAfterInstantiation方法 - 获取
InstantiationAwareBeanPostProcessor后置处理器并执行postProcessProperties方法(这里有一个重要的后置处理器AutowiredAnnotationBeanPostProcessor,就是在这个方法中完成注入的,逻辑比较长,大概的注入步骤就是解析依赖封装到InjectedElement,然后判断并检查依赖类型,然后调用上面的getBean方法获取Bean,即回到了上面的第7步(调用getBean获取bean),然后反射赋值:ReflectionUtils.makeAccessible(field);field.set(bean, value);) - 如果bean实现了
BeanNameAware、BeanClassLoaderAware、BeanFactoryAware接口,则调用对应方法; - 找到
BeanPostProcessor后置处理器,执行postProcessBeforeInitialization方法 - 执行初始化方法:先判断如果实现了
InitializingBean接口,则执行afterPropertiesSet方法;在判断如果有初始化方法,则执行初始化方法; - 找到
BeanPostProcessor后置处理器,执行postProcessAfterInitialization方法 - 再次尝试从缓存中获取当前bean;用于验证缓存中是不是当前bean;
- 判断是否DisposableBean,是的话就注册;
- 到此一个bean的创建步骤就完成了
从上面的过程中可以看出,当产生循环依赖时,原始对象会拥有循环依赖的代理对象,代理对象只会持有原始对象,使用spring注入的对象都是代理对象;另外当调用代理对象方法时,代理对象最终会调用原始对象的方法,在原始对象中this是指向自己的,因此直接使用this调用会导致代理失效;具体如图:

Bean后置处理器
注册过程
注册过程(这里的beanFactory也是容器创建时创建的容器):
- 通过
beanFactory.getBeanNamesForType方法获取容器中所有的后置处理器; - 按照执行BeanFactory后置处理器的类似逻辑对这些bean,分为实现了
PriorityOrdered接口的、实现了Ordered接口的和没有实现排序接口的三个list; - 依次对这三个list排序,然后注册到beanFactory中(注册过程实际就是调用
beanFactory.addBeanPostProcessor方法添加到成员变量中); - 最后将
ApplicationListenerDetector后置处理器也注册到beanFactory;
beanPostProcessor是在创建bean的过程中执行的,在上面bean的创建过程中其实已经设计到其执行过程,这里做一些小结;
小结
spring5.2.x中顶层的BeanPostProcessor接口有五个:
BeanPostProcessor:有两个抽象方法,分别是在调用初始化方法之前和之后执行,后面的几个后置处理器接口都继承自这个接口;
接口定义:
public interface BeanPostProcessor {
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
InstantiationAwareBeanPostProcessor:实例化bean后置处理器,其包含4个抽象方法:
postProcessBeforeInstantiation:会在创建bean对象之前执行,如果这个方法返回值不为空,则会将该返回值作为bean注册到容器中,跳过原始bean创建步骤中的实例化和初始化过程;也就是说这个方法给后置处理器一个机会来提前创建自定义的bean;postProcessAfterInstantiation:在bean对象被创建并封装到ObjectFactory后执行;其返回值代表后续是否需要为这个bean的属性赋值,也就是是否需要初始化;postProcessProperties:可以bean的属性值进行修改,上面提到的AutowiredAnnotationBeanPostProcessor后置处理器,就是在这个方法中调用metadata.inject(bean, beanName, pvs);完成注入的;postProcessPropertyValues:5.1以后已被弃用,用上面的方法代替;
SmartInstantiationAwareBeanPostProcessor:这个接口继承自InstantiationAwareBeanPostProcessor接口,添加了3个抽象方法:
predictBeanType:用于预测bean的类型determineCandidateConstructors:在实例化bean之前如果有这个方法,会尝试通过这个方法选择合适的构造器getEarlyBeanReference:从三级缓存中获取bean之前就会执行这个方法;这个方法在处理循环依赖、代理对象时非常有用
MergedBeanDefinitionPostProcessor:AutowiredAnnotationBeanPostProcessor这个重要的后置处理器也实现了这个接口,他有两个方法:
postProcessMergedBeanDefinition:在bean实例化后,放入三级缓存之前执行;一般可以用于获取当前bean及其父类中的所有信息;AutowiredAnnotationBeanPostProcessor就是在里获取和检查InjectionMetadata信息的;resetBeanDefinition:用于清除bean定义信息;
DestructionAwareBeanPostProcessor:bean销毁前回调的后置处理器,有两个方法:
postProcessBeforeDestruction:bean销毁之前的回调处理方法requiresDestruction:决定当前bean是否需要销毁
常用注解小结
bean注解
bean常用注解:
@Bean:配置bean,id默认是方法名@Scope:设置作用域,@Lazy-bean:设置懒加载(第一次调用时加载)initMethod:指定初始化方法(单实例:默认启动时执行,多实例:在获取时执行)destroyMethod:指定销毁方法(单实例:在关闭时执行(默认会检测close和shutdown方法),多实例:不执行)
@Conditional:按照条件注册bean(使用方式是实现Condition接口,在matches方法中编写具体条件,springboot中大量使用的注解,且扩展许多类似功能的注解,如@ConditionalOnBean、@ConditionalOnClass、@ConditionalOnMissingBean等);@Import:快速导入bean,功能类似@Bean,id默认是全类名- value除了可以有要导入的类,还可以有实现了
ImportSelector接口或者ImportBeanDefinitionRegistrar接口的实现类,用于筛选或添加要导入的bean;
- value除了可以有要导入的类,还可以有实现了
@PostConstruct:用在方法上,表示该方法会在bean会在创建并赋值完成后执行;@PreDestroy:用在方法上,表示该方法会在销毁bean之前执行;
赋值注解
赋值常用注解:
@Value:赋值,主要有下面三种用法:- 直接配置值;
- spel表达式赋值(
#{}); - 取配置文件中的值(
${});
@PropertySource:加载外部配置文件;@Profile:可以根据当前环境动态的激活和切换组件功能;- 用在bean上,表示满足指定环境时才注入Bean
- 用在类上,表示满足指定环境时才加载类;
- 没有环境标识注解,则在任何环境下都加载;
- 可以通过启动参数:
-Dspring.profiles.active=指定环境; - 也可以调用容器的setActiveProfiles方法设置环境(几乎不用);
注入注解
注入常用注解:
@Autowired:自动注入依赖,- 默认优先按照类型在容器中查找对应组件,如果找到多个,则将属性名称作为id在容器中查找;
- 默认至少要有一个可注入的bean,否则会报错(可以关闭);
@Qualifier:按名称注入bean;- 可以用在属性、普通方法、@bean方法(可以省略)、构造方法(如果只有一个有参构造方法,则可以省略)上;
- spring底层组件也可以注入
@Primary:@Autowired注入时,默认首选要装配的bean;@Resource:按名称注入(Java规范注解);@Inject:同@Autowired(Java规范注解,需要javax.inject依赖);
其他常见接口
bean
bean创建相关的常用接口:
FactoryBean:也可以注册Bean,使用方法是实现FactoryBean接口并配置到容器中,然后在getObject方法中返回实际需要注册的Bean即可(此时通过id调用getBean方法就可以返回对应的bean,如果要获取BeanFactory,需要在id前加&);InitializingBean:实现该接口的bean会在创建并赋值完成后调用afterPropertiesSet方法初始化bean;DisposableBean:实现该接口的bean会在bean销毁时调用destroy方法;BeanPostProcessor:bean的后置处理器,即在初始化前后执行(创建并赋值后,init方法的前后执行);(这个接口在spring源码中有多处使用,如上面的@PostConstruct生命周期注解、@Autowired注解、Aware接口、参数校验、bean赋值等);BeanFactoryPostProcessor:beanFactory后置处理器,在BeanFactory初始化之后执行,即,所有bean已经加载但还未创建的时候执行;可以使用这个接口添加一些自定义的bean到容器中;ApplicationListener:监听容器中的发布事件;
Aware
Aware:如果想在自定义组件中使用spring底层组件,可以实现对应的xxxAware接口,实现相关方法即可:
ApplicationContextAware:注入容器对象;BeanNameAware:注入bean的名字;EmbeddedValueResolverAware:注入spring字符串解析器(解析功能类似@Value);ApplicationEventPublisherAware:容器事件发布器ServletContextAware:用于web容器,注入ServletContext;ServletConfigAware:用于web容器,注入ServletConfigMessageSourceAware:用于国际化处理ResourceLoaderAware:注入资源加载器BeanFactoryAware:注入beanFactory;BeanFactoryAware:注入环境变量,可用于读取配置;ImportAware:注入AnnotationMetadata,可以处理一些注解信息;BeanClassLoaderAware:注入加载bean的类加载器:
本文详细解读Spring IoC容器的beanFactory功能、beanFactory预处理、BeanFactory后置处理器执行流程,以及Bean实例化和后置处理器注册过程,涉及常用注解和依赖注入。
1627

被折叠的 条评论
为什么被折叠?



