Bean的生命周期
2021-12-02 21:50:52 1 举报
AI智能生成
Bean的生命周期
作者其他创作
大纲/内容
bean的生命周期是指bean是如何创建、以及如何销毁的
bean的生成
生成beanDefinition
包括读取和扫描2种方式,读取通过BeanDefinitionReader,直接读取bean class对象,扫描通过BeanDefinitionScanner,通过基础包名扫描当前包以及子包下的class文件, 并按照过滤规则生成BeanDefinition并且注册进BeanDefinitionMap
BeanDefinitionReader
组合了BeanDefinitionRegistry
从资源中加载多个BeanDefinition,并调用BeanDefinitionRegistry进行注册
AnnotatedBeanDefinitionReader根据class对象生成beanName和BeanDefinition,注册到容器中,会处理的注解有:@Conditional,@Scope,@Lazy,@Primary,@DepensOn
得到的是AnnotatedGenericBeanDefinition
BeanDefinitionScanner
组合了BeanDefinitionRegistry
beanDefinition扫描器,实现类ClassPathBeanDefinitionScanner
根据包名扫描类路径下包以及子包的class文件得到BeanDefinition,调用BeanDefinitionRegistry进行注册
得到的是ScannedGenericBeanDefinition
@ComponentScan是通过它来实现的,要和@Configuaration一起,才会生效
读取class文件-->字节码解析得到MetadataReader-->过滤-->封装进ScannedGenericBeanDefinition-->生成beanName-->检查beanName重复-->注册进beanDefinitionMap
详细流程
底层使用ASM字节码解析技术读取class文件,而不是类加载的方式读取到JVM中,最终得到的ScannedGenericBeanDefinition的beanClass是类名称而不是Class对象,避免包中的所有class类在启动时都被不必要地加载
过滤条件取决于excludeFilters,includeFilters,@Conditional, 独立的(顶级外部类,静态内部类)、非抽象类,或者包含@Lookup方法的抽象类
默认的includeFilters是过滤@Component、@ManagedBean、@Named 的AnnotationTypeFilter, 也就是说默认生成basePackage下@Component标注的类
lookup用于单例bean要注入多例的场景
loopkup方法所在类可以是抽象类,spring都会为其生成cglib代理对象,
loopup方法再代理对象中会使用context.getbean,因此原方法可以返回null
loopkup方法所在类可以是抽象类,spring都会为其生成cglib代理对象,
loopup方法再代理对象中会使用context.getbean,因此原方法可以返回null
beanName生成: @Component、@ManagedBean、@Named指定了value,则为value,否则生成默认的beanName, 类的短名称,如果前两个字符都大写,则就是短名称,否则才是第一个字符小写的短名称
类的短名称:最后一个点号之后,cglib分隔符$$之前的,静态内部类$转成点号
生成beanName之后,检查beanName是否重复(beanDefinitionMap中是否存在),如果重复,且不是同一个class文件被重复扫描的情况,则报ConflictingBeanDefinitionException,如果是同一个class文件被重复扫描的情况,也不会替换,用原来的bean定义
合并beanDefinition
org.springframework.beans.factory.support.AbstractBeanFactory#getMergedLocalBeanDefinition
包括父子BeanDefinition的合并和父子beanFactory的合并,合并就是子BeanDefinition中未设置的属性继承父BeanDefinition的
BeanDefinition可以有父BeanDefinition
父子beanFactory中beanName相同的BeanDefinition会合并
加载类
org.springframework.beans.factory.support.AbstractBeanFactory#resolveBeanClass
bean实例化前要先类加载,beanDefinition中的beanClass属性是Object类型,在bean扫描生成beanDefinition阶段,该属性的值是类名,到这一步才会进行类加载,生成Class对象填充进去
类加载就是获取类加载器,再loadClass
类加载器的获取:优先使用beanFactory设置的类加载器,如果没有,获取当前线程的类加载器,还没有,获取当前类的类加载器,当前类的类加载器也为null时(当把当前类放到jre/lib,被bootstrap类加载器加载时),直接获取系统类加载器
如果要加载数组类,会先递归加载数组去掉所有维度之后的元素类型,再利用Array.newInstance(elementClass, 0).getClass()使用bootstrap类加载器加载
实例化前
调用bean的后置处理器的实例化前方法,InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation,返回不为空时,会直接使用返回值作为bean实例,并且跳过后续流程直接执行初始化后方法
实例化
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance
supplier创建对象:如果BeanDefinition中设置了Supplier,直接调用Supplier的get()得到对象
工厂方法创建对象
检查BeanDefinition中是否设置了factoryMethod,可以通过xml的factory-method、factory-bean或@Bean设置
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#instantiateUsingFactoryMethod
@Bean
可以是静态的或成员方法
成员方法beanDefinition的factoryMethodName是@Bean方法名,factoryBeanName是@Bean所在beanName,需要先获取所在bean,再method.invoke(bean), factoryBean会依赖@Bean
静态方法,factoryBeanName是null,method.invoke(null)
如果出现方法重载,BeanDefinition.isFactoryMethodUnique==false,这时会获取factoryClass中所有factoryMethod名称相同的方法,然后走推断构造方法流程
@Bean可以是成员方法、静态方法,如果factoryBean不是@Configuration(proxyBeanMethods = true), 也就是为@Configuration(proxyBeanMethods = false)或@Component时,factoryMethod还可以是private或final的,否则必须是可继承的
推断构造方法
AutowiredAnnotationBeanPostProcessor.determineCandidateConstructors
会判断bean中是否有@Lookup方法,如果没有,使用反射调用构造器实例化bean,否则生成一个代理对象
如果有一个构造器有@Autowired.required=true,其他构造器就不能有@Autowired,否则报BeanCreationException
如果有多个不带@Autowired的构造器,则会用无参构造器,没有报错
如果只有一个@Autowired.required=false的构造器,且没有无参构造器,不报错,但日志输出single autowire-marked constructor flagged as optional,this constructor is effectively required since there is no default constructor to fall back to
如果只有一个有参不带@Autowired的构造器,则用该构造器
如果有多个不带@Autowired的构造器,返回空
如果只有一个无参构造器,返回空
ConstructorResolver.autowireConstructor
如果有多个候选构造器,先排序,Public的排前面,作用域相同时,参数多的排前面,参数相同的情况下如果还有多个,则对它们进行打分,打分根据注入参数类型和方法形参类型有几级继承得出,一级加2,得分越低,类型匹配度越高,优先级就越高
注入点名称是构造器参数名称,通过字节码局部变量表获得
beandefinition的后置处理器
MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition
Bean实例化之后,属性填充之前,可以查询或修改合并之后的BeanDefinition
实现类有:CommonAnnotationBeanPostProcessor,AutowiredAnnotationBeanPostProcessor,查找注入点,查询bean的@PostConstruct,@PreDestory,@Resource、@Autowired、@Value等注解标注的方法或成员变量信息,以便填充和初始化时调用
实例化后方法
InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation
没怎么使用
依赖注入
InstantiationAwareBeanPostProcessor.postProcessProperties
根据刚才找到的注入点,查找创建依赖bean的实例,并注入
如果出现循环依赖,需要解决循环依赖
@Autowired会经过byType-->autowiredcandidate-->泛型-->@Qualifier-->@Primary-->@Priority-->byName过滤获取依赖, @Resource则是优先byName,当获取不到时再走@Autowired一样的流程,如果显式指定了名称,则只会byName
@Resource用在方法上时,只能注入第一个参数,注入点的名称就是去掉set前缀的方法名称,而@Autowired可以注入多个方法参数,并且名称是参数名称
spring内置的Aware
BeanNameAware,BeanClassLoaderAware,BeanFactoryAware
内置的Aware也就是不通过后置处理器来实现的,不管用什么容器都一定能获取到的组件
初始化前
BeanPostProcessor.postProcessBeforeInitialization
InitDestroyAnnotationBeanPostProcessor会在初始化前这个步骤中执行@PostConstruct的方法
ApplicationContextAwareProcessor会在初始化前这个步骤中进行其他Aware的回调: ApplicationContextAware、EnvironmentAware、ResourceLoaderAware、MessageSourceAware(国际化)、ApplicationEventPublisherAware
初始化
查看当前Bean对象是否实现了InitializingBean接口,如果实现了就调用其afterPropertiesSet()方法
初始化后
BeanPostProcessor.postProcessAfterInitialization
最后一个步骤,对Bean进行最终处理,Spring中的AOP就是基于初始化后实现的,初始化后返回的对象才是最终的Bean对象
Bean的销毁
bean的销毁是针对单例bean的,原型bean不会有销毁流程
创建Bean之后,注册销毁流程
有销毁方法的bean才会注册,销毁方法有哪些:DisposableBean.destroy、beanDefinition设置的destroyMethodName、AutoCloseable.close、beanDefinition.destroyMethodName是(infered)时,依次找close和shutdown、DestructionAwareBeanPostProcessor.requiresDestruction(bean)==true
注册实际上是用了适配器类DisposableBeanAdapter将bean封装起来,将不同的销毁逻辑统一适配成DisposableBean.close方法,然后放进Map<String/*beanName*/, Object/*DisposableBeanAdapter*/> disposableBeans
@PreDestroy方法实际上是通过DestructionAwareBeanPostProcessor实现的
容器关闭调用销毁流程
容器关闭有2种方式:手动调用close、调registerShutdownHook向JVM注册关闭钩子线程,关闭逻辑2者相同
容器关闭时,会调用beanFactory.destroySingletons销毁单例bean
单例池和二级、三级缓存中移除单例bean-->递归销毁当前bean所依赖的所有对象-->调用bean的销毁方法
0 条评论
下一页