前言
Bean的生命周期在spring中是很重要的一个概念,bean的生成和spring密不可分,想搞懂spring,先要了解bean的生命周期。
最核心的问题就是,了解bean的生命周期。
Bean的生命周期
spring的特点是IOC(控制反转),而启动spring就是为创建bean对象做准备,所以我们先了解bean是怎么创建的,需要什么。
下面这张图描述的就是bean完整的生命周期。(网图)
bean的生命周期从包扫描后开始。
生成BeanDefinition
扫描包路径,获取class文件,然后遍历生成BeanDefinition,在ClassPathScanningCandidateComponentProvider#scanCandidateComponents
代码语言:javascript复制/**
* 扫描候选的components
* @param basePackage
* @return
*/
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
// 扫描类,得到BeanDefinition
Set<BeanDefinition> candidates = new LinkedHashSet<>();
try {
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
resolveBasePackage(basePackage) '/' this.resourcePattern;
// 读取包路径下的资源文件
Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
boolean traceEnabled = logger.isTraceEnabled();
boolean debugEnabled = logger.isDebugEnabled();
for (Resource resource : resources) {
// 省略。。。
if (resource.isReadable()) {
try {
// MetadataReader包含了对应class的元信息以及注解元信息, MetadataReader
MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
// 判断一个类是不是Component
if (isCandidateComponent(metadataReader)) {
// 通过扫描@Component得到的BeanDefinition为ScannedGenericBeanDefinition
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
sbd.setResource(resource);
sbd.setSource(resource);
// 再进一步验证是不是备选的Component
if (isCandidateComponent(sbd)) {
// 省略。。。
candidates.add(sbd);
}
else {
// 省略。。。
}
}
else {
// 省略。。。
}
}
catch (Throwable ex) {
// 抛异常 省略。。。
}
}
else {
// 省略。。。
}
}
}
catch (IOException ex) {
// 抛异常 省略。。。
}
return candidates;
}
上述代码中,从resource获取到了MetadataReader
,它相当于是class文件解析后的信息。
这MetadataReader
对象有三个功能:
- 获取对应resource资源;
- 获取resource对应的class的元数据信息,包括名称、是否是注解、是否抽象等,具体可以查看类
ClassMetadata
的接口; - 获取resource对应的class上的注解信息,如当前类上有的注解,被注解标注的方法等;
这里生成的ScannedGenericBeanDefinition
中有一属性beanClass
,在这里存的是字符串,就是类全名,spring中使用ASM技术解析class文件,会得到class的所有信息,但不会加载类,所有在这里的beanClass保存了类名,beanClass的类型为Object,是因为,它可以存储不止字符串一种类型,也可以存储class类型,在用到这个类时才会加载,那么就会存class对象。
合并beanDefinition
在有了beanDefinition之后,会进行一次beanDefinition合并,其意义在于如果一个bean类继承了父类,而父类又设置了一些注解(或者是xml配置文件中的bean标签上设置了属性)或是属性,那么子类会继承这些属性,比如,父类有配置scope为原型,那么继承的子类没有重写,那么getBean得到也是一个原型,其原理就是因为做了合并,要注意的是,这个合并方式是基于父类进行合并的。
如下:
这里以xml方式进行演示,因为注解方式的有些不同,在生成beanDefinition时就默认设置了单例属性,xml这边呢,在合并beanDefinition之前没有就是没有,注解componentScan会默认设置的单例属性,但是设置是在合并方法里,下面代码可以看到。
代码语言:javascript复制 <bean id="parentService" class="com.lry.service.ParentService" scope="prototype"/>
<bean id="userService" class="com.lry.service.UserService" parent="parentService"/>
如下图,在走到合并beanDefinition方法的时候,userService的scope还是空,而父类parentService是prototype。
g)
在走过合并方法后,得到的userService的scope已经变了。
结果可以看到,userService继承了parentService,而parentService设置里scope为原型类型,userService也是原型类型。
再来看看源码里是怎样的DefaultListableBeanFactory.preInstantiateSingletons()
方法
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " this);
}
// 在spring启动时,就将bean的名字保存起来了
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// 循环bd,实例化非懒加载单例bean
for (String beanName : beanNames) {
// 对beanDefinition进行合并,基于合并后的BeanDefinition去创建bean
// 合并是子类合并到父类,才有完整的定义信息
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 非抽象,单例,非懒加载
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 判断是不是一个SmartFactoryBean
if (isFactoryBean(beanName)) {
// 如果是一个FactoryBean,那么需要加上前缀
Object bean = getBean(FACTORY_BEAN_PREFIX beanName);
if (bean instanceof FactoryBean) {
final FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
// eager:急切的意思,立马初始化
// smartFactoryBean 有一个接口,isEagerInit,是否立即初始化
// System.getSecurityManager() 是安全管理器,不用管
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
// 是立即初始化,就根据beanName去生成FactoryBean中所生成的Bean对象
getBean(beanName);
}
}
}
else {
// 根据beanName去创建bean
getBean(beanName);
}
}
}
// 创建完所有的单例bean之后,判断某个单例bean是不是SmartInitializingSingleton,如果是执行afterSingletonsInstantiated()方法
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
进入getMergedLocalBeanDefinition
方法,一开始,mergedBeanDefinitions
是空的,都是在执行这个方法后添加的。
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
// 从已合并的容器中取
RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
if (mbd != null && !mbd.stale) {
return mbd;
}
return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}
代码语言:javascript复制protected RootBeanDefinition getMergedBeanDefinition(
String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
throws BeanDefinitionStoreException {
// bd 可以说是我们要拿的bean的beanDefinition;
synchronized (this.mergedBeanDefinitions) {
RootBeanDefinition mbd = null;
RootBeanDefinition previous = null;
if (containingBd == null) {
mbd = this.mergedBeanDefinitions.get(beanName);
}
// 取不到合并的beanDefinition
if (mbd == null || mbd.stale) {
previous = mbd;
// 如果bd的父bd为空,说明它是个rootBeanDefinition
if (bd.getParentName() == null) {
// RootBeanDefinition没有父BeanDefinition
if (bd instanceof RootBeanDefinition) {
// 如果bd已经是rootBeanDefinition,就克隆一份返回
mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
}
else {
// 还不是rootBeanDefinition,就生成一个
mbd = new RootBeanDefinition(bd);
}
}
else {
// bd存在父类
BeanDefinition pbd;
try {
// 父bd的beanName
String parentBeanName = transformedBeanName(bd.getParentName());
if (!beanName.equals(parentBeanName)) {
// 递归调用,因为父bean 还可能有父bean,所以再次调用合并得到父的beanDefinition
pbd = getMergedBeanDefinition(parentBeanName);
}
else {
// 一般不会走
// 到父容器中找对应的bean,然后进行合并,合并也发生在父容器中
BeanFactory parent = getParentBeanFactory();
if (parent instanceof ConfigurableBeanFactory) {
pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
}
else {
// 抛异常 省略。。。
}
}
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
"Could not resolve parent bean definition '" bd.getParentName() "'", ex);
}
// pbd表示父BeanDefinition, bd表示本BeanDefinition
mbd = new RootBeanDefinition(pbd);
// 基于mbd,将bd属性设置进去,就是合并,这里可以说是覆盖
mbd.overrideFrom(bd);
}
// 如果没有设置scope,就设置默认为singleton
if (!StringUtils.hasLength(mbd.getScope())) {
mbd.setScope(SCOPE_SINGLETON);
}
// 如果某个<bean/>内包含了一个内部<bean/>,containingBd表示外部bean, mbd表示内部bean
// 外部bean如果不是单例bean,内部bean是单例的,那么则把内部bean的scope设置为和外部bean的scope一样的
if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
mbd.setScope(containingBd.getScope());
}
// 将合并后的bd放入到mergedBeanDefinitions这个map中
// 之后还是可能被清空的,因为bd可能被修改
if (containingBd == null && isCacheBeanMetadata()) {
this.mergedBeanDefinitions.put(beanName, mbd);
}
}
if (previous != null) {
copyRelevantMergedBeanDefinitionCaches(previous, mbd);
}
return mbd;
}
}
这里需要讲一下这个beanName获取的方式,因为上面有这样的方法。
传进去beanName可以有3种:
- beanName即bean的名称,也可以说是实际名称
- factoryBean 的名称,而要得到factoryBean的name需要转义,不然获取的就是它生成的bean,就和第一点的一样。如
&userService
,在beanName前面有一个前缀。 - 别名;是我们为这些bean设置的名称
protected String transformedBeanName(String name) {
return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}
BeanFactoryUtils.transformedBeanName(name)
方法是为了拿到实际的beanName,将factoryBean之前的&
去除。
public static String transformedBeanName(String name) {
Assert.notNull(name, "'name' must not be null");
// 如果beanName没有以&开头,则直接返回
if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
return name;
}
// 如果beanName以&开头,截取&后的beanName,并且把截取前后的name存在transformedBeanNameCache中
return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
do {
beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
}
while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
return beanName;
});
}
canonicalName
方法这里是获取实际的beanName,因为在spring中各种处理都是围绕着实际的name进行的。
public String canonicalName(String name) {
String canonicalName = name;
String resolvedName;
do {
// 从aliasMap中获取到对应的实际名称,在aliasMap中通过别名,保存着实际的类名
resolvedName = this.aliasMap.get(canonicalName);
if (resolvedName != null) {
canonicalName = resolvedName;
}
}
while (resolvedName != null);
return canonicalName;
}
加载类
在合并完beanDefinition后,又回到了DefaultListableBeanFactory.preInstantiateSingletons()
方法
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " this);
}
// 在spring启动时,就将bean的名字保存起来了
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// 循环bd,实例化非懒加载单例bean
for (String beanName : beanNames) {
// 对beanDefinition进行合并,基于合并后的BeanDefinition去创建bean
// 合并是子类合并到父类,才有完整的定义信息
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 非抽象,单例,非懒加载
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 判断是不是一个SmartFactoryBean
// 省略。。。
if(){}
else {
// 根据beanName去创建bean
getBean(beanName);
}
}
}
// 创建完所有的单例bean之后,判断某个单例bean是不是SmartInitializingSingleton,如果是执行afterSin
// 省略。。。
}
在方法下面有一个getBean的方法,进入getBean(beanName);
方法,在doGetBean
方法里你会找到createBean这个方法,类就是在createBean中被加载的。
下面看doGetBean
,代码有点长,分段慢慢看,加载类是在创建bean的时候创建的,但是这里还不是底层创建bean的地方。
// 对beanName进行转换 name如果是"&lubanFactoryBean",那么beanName就是"lubanFactoryBean"
final String beanName = transformedBeanName(name);
Object bean;
// 从单例池中取单例bean
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
// 省略。。
}
// 判断sharedInstance是不是FactoryBean,如果是FactoryBean,那么真正需要拿到的是getObject方法所返回的对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
上面这段是从容器中获取bean,或者是从factoryBean获取Object;
当从单例池中获取不到bean时,先判断是否在创建中(创建bean是都会先添加记号),然后如果是还没创建,那么再从父容器中找找看,找到旧直接返回。
代码语言:javascript复制// 原型bean正在创建中
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
// 当前BeanFactory中不存beanName对象的BeanDefinition,那么则从ParentBeanFactory中去获取
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// 这里意思就是,当前容器拿不到,那么让父容器去拿,有可能在父容器就有
// Not found -> check parent.
// 原始的beanName
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
上面两步中,都没拿到bean,那么就需要创建了,在创建之前,要添加一个记号,表示它要创建这个bean了,其他人等着。
代码语言:javascript复制 // 走到这一步,就是还没拿到bean,所以要创建Bean
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
这里又获取了一次beanDefinition,因为在这个过程中,beanDefinition很可能被修改,所以要一直保持最新的。
然后查看这次要创建的bean是否有依赖了其他bean,有依赖的需要先创建依赖的bean,所以这里又调用了一次getBean,实现了递归,因为不能保证依赖的bean,是不是又依赖了另一个bean。
代码语言:javascript复制// 得到合并后的BeanDefinition;获取最新的定义
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 加载DependsOn的bean(依赖的bean)
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
// 判断beanName是不是也被dep依赖了,如果是,就是相互依赖
if (isDependent(beanName, dep)) {
// 抛异常 省略。。。
}
// 存在在两个map中
// 1. dependentBeanMap,key为dep, value是一个LinkedHashSet,表示dep被哪些bean依赖了
// 2. dependenciesForBeanMap,key为beanName,value是一个LinkedHashSet,表示beanName依赖了哪些bean
registerDependentBean(dep, beanName);
try {
// 先去拿依赖的bean,然后又是递归,再查找依赖的bean的依赖的bean
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
// 抛异常 省略。。。
}
}
}
依赖检验通过后,这里是根据bean的作用域去创建bean,如果是singleton的话,调用createBean方法生成bean,然后添加到单例池总。
而如果是原型bean的话,就会直接调用createBean生成。
代码语言:javascript复制// 根据Scope去创建bean
if (mbd.isSingleton()) {
// 获取单例bean,如果获取不到则创建一个bean,并且放入单例池中
// 这里使用了函数式接口
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// 抛异常 省略。。。
}
});
// sharedInstance可能是一个FactoryBean,所以需要单独再去factoryBeanObjectCache中去获取对应的对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
// 记录在创建的bean
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
// 创建完后,就移除
afterPrototypeCreation(beanName);
}
// 因为是单例的,创建出来后,就没添加单例池
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
而如果都不是singleton和prototype,那么就是sessionScope、RequestScope这些的作用域,
代码语言:javascript复制else {
// 这里的scope是sessionScope和RequestScope,
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
// 抛异常 省略。。。
}
try {
// 这里调用的是`AbstractRequestAttributesScope`里的get方法
Object scopedInstance = scope.get(beanName, () -> {
// 记录在创建的bean
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
// 移除记录
afterPrototypeCreation(beanName);
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
// 抛异常 省略。。。
}
}
而scope.get方法是AbstractRequestAttributesScope
里的方法,resquestScope 和 sessionScope 都继承这个对象,也都调用这一个方法,在attributes.getAttribute
和attributes.setAttribute
里它都有去判断是哪一个scope。
看一下这个scope.get方法:
代码语言:javascript复制public Object get(String name, ObjectFactory<?> objectFactory) {
RequestAttributes attributes = RequestContextHolder.currentRequestAttributes();
// 从属性中获取
Object scopedObject = attributes.getAttribute(name, getScope());
if (scopedObject == null) {
// 拿不到就是没有,那么从函数式接口中获取,就是在外层方法我们返回的值
scopedObject = objectFactory.getObject();
// 拿到之后设置到属性中
// request -> request.setAttribute(name, value);
// session -> session.setAttribute(name, value);
attributes.setAttribute(name, scopedObject, getScope());
// 它这里再次进行了取值,注释上说校验,我觉得它是以从会话或是请求对象中取的为准,
// 而再次取值还是没取到,它也没办法,还是得继续处理,感觉作用不大
Object retrievedObject = attributes.getAttribute(name, getScope());
if (retrievedObject != null) {
scopedObject = retrievedObject;
}
}
return scopedObject;
}
最后就是对生成的bean进行类型转化,就是会判断是否是我们需要的 bean,这里的类型转化器,是获取的自定义的,也就是可以获取我们自定义的转化器。
代码语言:javascript复制 // 根据beanName获取到的bean的类型是否和requiredType匹配,如果不配则进行类型转化
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
}
catch (TypeMismatchException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Failed to convert bean '" name "' to required type '"
ClassUtils.getQualifiedName(requiredType) "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
上面在创建单例和原型bean(singleton、prototype)时,都调用了createBean
方法,这里再详细看一下
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
// 省略。。。
RootBeanDefinition mbdToUse = mbd;
// 拿到bean Class
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
// 这里是没有beanClass,这里的beanClass指的是类对象class
// 之前在得到beanDefinition时,存的是类全名(字符串)
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
try {
// 对通过XML定义的bean中的look-up方法进行预处理
// 对于@Lookup注解标注的方法不在这里进行处理,@AutowiredAnnotationBeanPostProcessor会处理@Lookup注解
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
// 抛异常 省略。。。
}
try {
// 1、实例化前 null
Object bean = resolveBeforeInstantiation(beanName, mbdToUse); // 对象
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
// 抛异常 省略。。。
}
try {
// 创建bean Spring自带的创建bean的方法
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" beanName "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
throw ex;
}
catch (Throwable ex) {
// 抛异常 省略。。。
}
}
上面代码中第一行是Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
加载类就是在这里处进行的,进入里面是下面这段,大概意思是如果beanClass的类型是class,就直接返回,不是就根据类名加载。
// 直接返回beanClass
if (mbd.hasBeanClass()) {
return mbd.getBeanClass();
}
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>) () ->
doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
}
else {
// 加载BeanDefinition中beanClass中所指定的类名对应的类
return doResolveBeanClass(mbd, typesToMatch);
}
实例化前
接着看createBean方法,里面有这个方法resolveBeforeInstantiation
// 1、实例化前 null
Object bean = resolveBeforeInstantiation(beanName, mbdToUse); // 对象
if (bean != null) {
return bean;
}
代码语言:javascript复制protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
// beforeInstantiationResolved为null或true
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// isSynthetic 是由编译器引入字段、方法、类或其他结构,复杂东西,忽略
// hasInstantiationAwareBeanPostProcessors 是否有实例化bean的后置处理器
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
// 确定bean的类型
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
// 实例化前
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
// 在bean返回之前,做一些后置的初始化操作进行干涉
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
这里执行实例化bean的处理器,有两个方法applyBeanPostProcessorsBeforeInstantiation
和 applyBeanPostProcessorsAfterInitialization
,他们都是接口InstantiationAwareBeanPostProcessor
,它提供了一些方法,可以对bean进行干涉,并且每一个bean都会走这个逻辑;在看上面代码中的这段,是调用了我们自己的后置处理器返回了一个bean,然后返回,这里是bean的生命周期都结束了,因为bean的生成过程由我们自己去控制了,再返回来的时候已经是一个完整的bean了,所以这里要做到bean初始化后的操作,就需要在执行bean的后置初始化操作,所以才有的 if 判断中的内容。
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
// 在bean返回之前,做一些后置的初始化操作进行干涉
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
进入applyBeanPostProcessorsBeforeInstantiation
,看getBeanPostProcessors
方法,它把所有的postProcess都取出来了。
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
return null;
}
关于后置处理器我举个例子:
实现InstantiationAwareBeanPostProcessor
,然后通过方法返回我定义的一个实例,那么之后创建的bean就会如我所愿已经设置好了自定义User。那么之前也说了,每个bean的创建都会遍历postProcess,所有这里我加了if判断。
@Component
public class CustomPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if (beanClass.equals(UserService.class)) {
User user = new User();
user.setName("before post processor");
UserService userService = new UserService();
userService.setUser(user);
return userService;
}
return null;
}
}
下面这段,这里要注意下就是执行applyBeanPostProcessorsAfterInitialization
方法(实例化后后置处理器),这个处理器方法默认是返回bean的,如果其中一个处理器返回了null,那么循环就结束了,之后的处理器就不会执行。
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
// 这里返回null就直接返回了
if (current == null) {
return result;
}
result = current;
}
return result;
}
推断构造方法
这篇博客大佬有详细分析:https://blog.csdn.net/xjk201/article/details/109996292
再回到createBean
方法,resolveBeforeInstantiation
实例化前的操作完了之后,接着执行doCreateBean
;如果在resolveBeforeInstantiation
中得到bean了,那么就不会走doCreateBean方法了。
try {
// 1、实例化前 null
Object bean = resolveBeforeInstantiation(beanName, mbdToUse); // 对象
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
// 省略。。。
}
try {
// 创建bean Spring自带的创建bean的方法
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" beanName "'");
}
return beanInstance;
}
在前面resolveBeforeInstantiation
没有得到bean,这里是进入doCreateBean
方法去创建bean。然后找到createBeanInstance
方法,就下面这句
// 2、实例化
if (instanceWrapper == null) {
// 创建bean实例 new USerSerive()
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
进入createBeanInstance
方法,推断构造器的主要逻辑从这里开始,下面代码中,第一点是获取class,第2,第3点都是实例化bean对象,但这两步并不是我们要看的方法,这两步就相当于我们手动实例化一样,因为是经由我们的方法去实例化的,已经跳过了推断构造这个过程了。所以我们要从第4点开始
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// 创建一个bean实例(返回一个原始对象)
// Make sure bean class is actually resolved at this point.
// 1. 得到bean的class,并验证class的访问权限是不是public
Class<?> beanClass = resolveBeanClass(mbd, beanName);
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " beanClass.getName());
}
// 2. 这是Spring提供给开发者的扩展点
// 如果我们要自己来实现创建对象的过程, 那么就可以提供一个Supplier的实现类,
// 当一个BeanDefinition中存在一个Supplier实现类的时候, Spring就利用这个类的get方法来获取实例,
// 而不再走Spring创建对象的逻辑
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
// 3.通过factoryMethod实例化这个bean
// factorMethod这个名称在xml中还是比较常见的, 即通过工厂方法来创建bean对象
// 如果一个bean对象是由@Bean注解创建的, 那么该对象就会走instantiateUsingFactoryMethod方法来创建的
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// Shortcut when re-creating the same bean...
boolean resolved = false;
boolean autowireNecessary = false;
// 4. 如果在创建bean时没有手动指定构造方法的参数,那么则看当前BeanDefinition是不是已经确定了要使用的构造方法和构造方法参数
// 注意:如果没有手动指定参数,那么就肯定时自动推断出来的,所以一旦发现当前BeanDefinition中已经确定了要使用的构造方法和构造方法参数,
// 那么就要使用autowireConstructor()方法来构造一个bean对象
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
// 该BeanDefinition是否已经决定了要使用的构造方法或工厂方法
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
// 该BeanDefinition是否已经决定了要使用的构造方法参数
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
// resolved为true,表示当前bean的构造方法已经确定出来了
// autowireNecessary表示
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null, null);
}
else {
// 如果构造方法已经确定了,但是没有确定构造方法参数,那就表示没有构造方法参数,用无参的构造方法来实例化bean
return instantiateBean(beanName, mbd);
}
}
// Candidate constructors for autowiring?
// 获取@Autowire的注解的构造器
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
// 通过BeanPostProcessor找出了构造方法
// 或者BeanDefinition的autowire属性为AUTOWIRE_CONSTRUCTOR
// 或者BeanDefinition中指定了构造方法参数值
// 或者在getBean()时指定了args
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
// 进行构造方法推断并实例化
return autowireConstructor(beanName, mbd, ctors, args);
}
// Preferred constructors for default construction?
// 没啥用
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}
// No special handling: simply use no-arg constructor.
// 用无参的构造方法来实例化bean
return instantiateBean(beanName, mbd);
}
实例化
上面的代码的最后,在createBeanInstance
方法后面,通过反射生成得到实例,所有加载类的作用就是反射创建bean的实例。
return instantiateBean(beanName, mbd);
BeanDefinition后置处理器处理
再返回到doCreateBean
方法,在上面实例化得到对象后,有一个后置处理器,这个处理器是为了做依赖注入(填充属性)做准备,它在这个地方,的作用是查找注入点。
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
代码语言:javascript复制protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof MergedBeanDefinitionPostProcessor) {
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
}
}
在这步,我们也可以自定义一些处理器,对实例化好的bean做一些处理,在这里改beanClass是无效的,以为你bean已经实例化好了。下面是一个自定义的例子:
代码语言:javascript复制@Component
public class CustomMergedBeanDefinitionPostProcessor implements MergedBeanDefinitionPostProcessor {
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
Class<?> beanClass = beanDefinition.getBeanClass();
if (beanClass.equals(UserService.class)) {
MenuService menuService = new MenuService();
menuService.setName("MergedBeanDefinitionPostProcessor。。。");
beanDefinition.getPropertyValues().add("menuService", menuService);
}
}
}
填充属性
这里基本就是依赖注入的东西了。之后会详细一篇;
在这里就是查找注入点,然后对需要注入的属性进行填充,比如我们xml里配置了注入类型,或是使用了@Autowired等这些,就是要注入的。
代码语言:javascript复制// 3、填充属性 @Autowired
populateBean(beanName, mbd, instanceWrapper);
执行aware
进入initializeBean
方法
exposedObject = initializeBean(beanName, exposedObject, mbd);
代码语言:javascript复制// 4.1、执行Aware
invokeAwareMethods(beanName, bean);
代码语言:javascript复制if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
aware接口的作用就是能够获取的容器服务。
初始化前
紧接着
代码语言:javascript复制// 4.2、初始化前
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
代码语言:javascript复制public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
它里通过后置处理器得到对象current
,这里的处理和之前看到不一样,这里是只要一个处理器返回null,就不会再执行后面的处理器了。
初始化
代码语言:javascript复制// 4.3、初始化
invokeInitMethods(beanName, wrappedBean, mbd);
代码语言:javascript复制protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
boolean isInitializingBean = (bean instanceof InitializingBean);
// 第一:执行isInitializingBean的afterPropertiesSet
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking afterPropertiesSet() on bean with name '" beanName "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
// 第二:执行InitMethod方法
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd); // init-method=""
}
}
}
这边先是执行了InitializingBean
的afterPropertiesSet
方法,然后又执行initMethod
方法,这两个区别是afterPropertiesSet
直接调用方法执行,而initMethod
是反射执行的,而且支持private的访问类型。
初始化后
紧接着后面又有处理器,aop的就是在这里处理的,同样是返回null就会结束处理器链调用。
代码语言:javascript复制// 4.4、初始化后
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
Bean 的销毁
- 容器关闭
- 发布ContextClosedEvent事件
- 调用LifecycleProcessor的onClose方法
- 销毁单例bean
protected void doClose() {
// Check whether an actual close attempt is necessary...
if (this.active.get() && this.closed.compareAndSet(false, true)) {
if (logger.isDebugEnabled()) {
logger.debug("Closing " this);
}
LiveBeansView.unregisterApplicationContext(this);
try {
// Publish shutdown event.
publishEvent(new ContextClosedEvent(this));
}
catch (Throwable ex) {
logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
}
// Stop all Lifecycle beans, to avoid delays during individual destruction.
if (this.lifecycleProcessor != null) {
try {
this.lifecycleProcessor.onClose();
}
catch (Throwable ex) {
logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
}
}
// Destroy all cached singletons in the context's BeanFactory.
destroyBeans();
// Close the state of this context itself.
closeBeanFactory();
// Let subclasses do some final clean-up if they wish...
onClose();
// Reset local application listeners to pre-refresh state.
if (this.earlyApplicationListeners != null) {
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
// Switch to inactive.
this.active.set(false);
}
}
总结
我用思维导图把上面的流程捋了一遍。
深色的就是上面的各个步骤,偏绿色,和绿色的是后置处理器的部分,一共6次调用,就是说我们有6次机会修改bean,还每一算上填充属性里的后置处理器。
深蓝色和蓝绿色的是上面的生命周期阶段;
绿色字体和蓝绿色的是后置处理器处理的调用;
蓝色字体的是可以自定义实现的bean初始化的地方;
那么还是围绕问题回顾一下
为什么要有beanDefinition
spring在启动后扫描,会得到beanDefinition,然后在实例化bean时,通过getBean获取一个bean,要判断这个bean是否懒加载,是否单例等等,那么这时候就不能再去解析了,因为在启动时就扫描解析过一次了,所以在第一次扫描解析会把bean的各种信息保存用来创建bean,这就是beanDefinition的作用
为什么要用asm技术,不直接接着类
首先asm解析技术的效率高,在第一次扫描后把class解析成beanDefinition,然后在实例化bean的时候,再加载类,这个步骤的优势在于,减少spring启动的时间,如果项目工程较大,拥有的class比较多,那么直接去加载类就会使得启动变慢
为什么需要合并
java类,有父类,子类,子类继承父类的属性和方法,然后子类拥有父类的属性和方法,而beanDefinition解析的class信息,没有父类的信息,所以要进行合并。
后置处理器的作用
后置处理器可以让我们在spring在实例化bean时,可以对bean的生成进行一些自定义的操作。