Spring bean的生命周期涉及的知识点太多而且比较复杂,很难在一篇文章中把Spring bean生命周期所有的方面都讲清楚。所以按照几条线来分别整理,最后再写一篇汇总的文章串联起来。
本文依然基于annotation注解配置的方式进行分析。
回顾一下我们说过Spring bean的生命周期主要大概有以下几个步骤:
创建bean的实例
给实例化出来的bean填充属性
初始化bean
通过IOC容器使用bean
容器关闭时销毁bean
本文就对第二阶段bean的依赖注入(Dependency Injection)分以下几个问题来整理:
什么是Spring容器和依赖注入?
何时发生依赖注入?
Spring依赖注入的源码
什么是Spring容器和依赖注入? 上次我们说过,IOC是一种重要的设计理念,而Spring IOC又是基于这个理念在Spring framework实现的高级特性。Spring IOC具备以下两个特性:
准备Bean的整个生命周期需要的数据: 在这一步中,Spring容器会定位配置文件,加载各种Class文件,并且将其解析成BeanDefinition(重要数据类型),这个BeanDefinition会贯穿Spring容器及Spring运行环境初始化的整个流程,是我们尤其要关注的数据基础;
管理整个Bean的生命周期: 完成bean实例化、完成各个bean之间依赖关系注入(本文所分析)、完成bean的初始化及销毁。
依赖注入和属性注入的区别 依赖注入其实是属性注入的一种特殊情形,特殊之处就在于它要注入的是bean,而不是String、List、Array这种。
我们通过@Autowire标签来完成依赖注入。
何时发生依赖注入? 回看之前我们分析的bean实例化源码,可以看到一丝线索。
在AnnotationConfigApplicationContext初始化时,调用关键方法refresh():
1 2 3 4 5 6 public AnnotationConfigApplicationContext (Class<?>... componentClasses) { this (); register(componentClasses); refresh(); }
Spring初始化入口refresh(省略了部分代码,提升阅读体验):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 @Override public void refresh () throws BeansException, IllegalStateException { synchronized (this .startupShutdownMonitor) { prepareRefresh(); ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); prepareBeanFactory(beanFactory); try { postProcessBeanFactory(beanFactory); invokeBeanFactoryPostProcessors(beanFactory); registerBeanPostProcessors(beanFactory); ... finishBeanFactoryInitialization(beanFactory); finishRefresh(); } } }
点进去finishBeanFactoryInitialization(beanFactory)里头有个初始化non-lazy-init bean的函数preInstantiateSingletons(),具体逻辑如下:
对beanNames集合遍历获取每个BeanDefinition;
判断是否是懒加载的,如果不是则继续处理(non-lazy-init bean不做处理);
判断是否是factorybean如果不是则进行实例化并依赖注入。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 @Override public void preInstantiateSingletons () throws BeansException { List<String> beanNames = new ArrayList<>(this .beanDefinitionNames); for (String beanName : beanNames) { RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { if (isFactoryBean(beanName)) { Object bean = getBean(FACTORY_BEAN_PREFIX + beanName); if (bean instanceof FactoryBean) { final FactoryBean<?> factory = (FactoryBean<?>) bean; boolean isEagerInit; 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) { getBean(beanName); } } } else { getBean(beanName); } } } }
对于懒加载的bean,本质上就是手动去调用这个getBean(beanName)方法。所以在此我们找到了依赖注入的入口。
Spring依赖注入的源码 依赖注入实现的入口 getBean()是个空壳方法,里面直接调用doGetBean():
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 protected <T> T doGetBean (final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException { ... if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, () -> { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { destroySingleton(beanName); throw ex; } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } ... }
这个getSingleton()的第二个参数使用lambda表达式传入createBean()方法,真正创建bean实例的方法在这个createBean()方法里面。
createBean()中经过一系列预处理,最后调doCreateBean()方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 protected Object doCreateBean (final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { BeanWrapper instanceWrapper = null ; if (mbd.isSingleton()) { instanceWrapper = this .factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null ) { instanceWrapper = createBeanInstance(beanName, mbd, args); } final Object bean = instanceWrapper.getWrappedInstance(); Class<?> beanType = instanceWrapper.getWrappedClass(); Object exposedObject = bean; try { populateBean(beanName, mbd, instanceWrapper); exposedObject = initializeBean(beanName, exposedObject, mbd); } catch (Throwable ex) { } try { registerDisposableBeanIfNecessary(beanName, bean, mbd); } catch (BeanDefinitionValidationException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Invalid destruction signature" , ex); } return exposedObject; }
我们这里关注第二步进行依赖注入的代码populateBean(beanName, mbd, instanceWrapper):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 protected void populateBean (String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null ); int resolvedAutowireMode = mbd.getResolvedAutowireMode(); if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); if (resolvedAutowireMode == AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE); PropertyDescriptor[] filteredPds = null ; if (hasInstAwareBpps) { if (pvs == null ) { pvs = mbd.getPropertyValues(); } for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); if (pvsToUse == null ) { if (filteredPds == null ) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvsToUse == null ) { return ; } } pvs = pvsToUse; } } } if (pvs != null ) { applyPropertyValues(beanName, mbd, bw, pvs); } }
注解形式注入的源码 基于注解的方式我们关注PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName)
这个方法调用。看一下AutowiredAnnotationBeanPostProcessor中的postProcessProperties()方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @Override public PropertyValues postProcessProperties (PropertyValues pvs, Object bean, String beanName) { InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs); try { metadata.inject(bean, beanName, pvs); } catch (BeanCreationException ex) { throw ex; } catch (Throwable ex) { throw new BeanCreationException(beanName, "Injection of autowired dependencies failed" , ex); } return pvs; }
InjectionMetadata这个类封装了依赖的bean信息private final Collection<InjectedElement> injectedElements;
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public void inject (Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { Collection<InjectedElement> checkedElements = this .checkedElements; Collection<InjectedElement> elementsToIterate = (checkedElements != null ? checkedElements : this .injectedElements); if (!elementsToIterate.isEmpty()) { for (InjectedElement element : elementsToIterate) { if (logger.isTraceEnabled()) { logger.trace("Processing injected element of bean '" + beanName + "': " + element); } element.inject(target, beanName, pvs); } } }
XML形式注入的源码 在populateBean()中最后面有通过XML形式注入的入口applyPropertyValues(beanName, mbd, bw, pvs);
,这个方法主要做的事情是把属性转换为相应的类的属性类型,最终注入到bean中,主要分为三个步骤:
判断是否完成转换;
进行转换;
注入到bean中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 protected void applyPropertyValues (String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) { MutablePropertyValues mpvs = null ; List<PropertyValue> original; if (pvs instanceof MutablePropertyValues) { mpvs = (MutablePropertyValues) pvs; if (mpvs.isConverted()) { try { bw.setPropertyValues(mpvs); return ; } catch (BeansException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Error setting property values" , ex); } } original = mpvs.getPropertyValueList(); } else { original = Arrays.asList(pvs.getPropertyValues()); } TypeConverter converter = getCustomTypeConverter(); if (converter == null ) { converter = bw; } BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this , beanName, mbd, converter); List<PropertyValue> deepCopy = new ArrayList<>(original.size()); boolean resolveNecessary = false ; for (PropertyValue pv : original) { if (pv.isConverted()) { deepCopy.add(pv); } else { String propertyName = pv.getName(); Object originalValue = pv.getValue(); if (originalValue == AutowiredPropertyMarker.INSTANCE) { Method writeMethod = bw.getPropertyDescriptor(propertyName).getWriteMethod(); if (writeMethod == null ) { throw new IllegalArgumentException("Autowire marker for property without write method: " + pv); } originalValue = new DependencyDescriptor(new MethodParameter(writeMethod, 0 ), true ); } Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue); Object convertedValue = resolvedValue; boolean convertible = bw.isWritableProperty(propertyName) && !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName); if (convertible) { convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter); } if (resolvedValue == originalValue) { if (convertible) { pv.setConvertedValue(convertedValue); } deepCopy.add(pv); } else if (convertible && originalValue instanceof TypedStringValue && !((TypedStringValue) originalValue).isDynamic() && !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) { pv.setConvertedValue(convertedValue); deepCopy.add(pv); } else { resolveNecessary = true ; deepCopy.add(new PropertyValue(pv, convertedValue)); } } } if (mpvs != null && !resolveNecessary) { mpvs.setConverted(); } try { bw.setPropertyValues(new MutablePropertyValues(deepCopy)); } catch (BeansException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Error setting property values" , ex); } }
Spring中的循环依赖 Spring是支持循环依赖的,有人就要问循环是怎么解决的?其实这里有一个问题是:依赖注入的是对象,而不是bean;循环依赖是说bean A依赖对象 B,bean B依赖对象 A。所以上面我们分析的实例化对象之后,会首先将这个对象暴露出来,这就是解决循环依赖的一个关键点,具体的步骤是:
A在推断完构造方法,并且通过反射new出来一个A对象之后,将A对象暴露出来,下一步要做依赖注入;
发现要依赖B,那么就开始B的bean初始化,并且将这个new出来的A对象放到一个set集合缓存当中;
B在完成反射new对象之后,下一步也是要依赖注入,发现要依赖A;
因为依赖指的是依赖对象,而不是依赖bean,所以这时候B就可以去那个set中拿到A的实例,注入A的对象;
到这里为止,B完成了bean的初始化,并且放到单例池singletonMap中了,接下来A继续走流程;
A在单例池中找到了B的bean,所以A也能注入B了;
A也走完流程,完成bean初始化并且放到单例池中,至此循环依赖处理完成。
这里的代码读者可以自行追一下。
总结 依赖注入部分主要是以下几点:
依赖注入是bean生命周期的重要一环;
依赖注入是属性注入的一种,只不过注入的是bean类型;
何时发生依赖注入;
两种注入方式(注解方式和XML方式)的源码。