整理一下Spring bean的实例化相关内容。创建Spring bean实例是Spring bean生命周期的第一阶段。
本文基于annotation注解配置的方式进行分析。
bean实例化入口 Spring bean的生命周期主要有如下几个步骤:
创建bean的实例
给实例化出来的bean填充属性
初始化bean
通过IOC容器使用bean
容器关闭时销毁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); } } } }
getBean()方法是实现bean初始化以及依赖注入的函数,本篇我们只关注bean的初始化。
对于lazy-init和non-lazy-init此时开始分叉。
初始化懒加载bean 上面preInstantiateSingletons()方法中看到如果不是懒加载的bean则执行初始化,实际上是Spring帮用户调用了getBean()方法来完成的。
所以在懒加载bean的情景中,preInstantiateSingletons()方法直接返回,我们在使用bean的时候手动去getBean(),也就是完成了后续的初始化过程,此谓“懒加载”。
1 2 3 4 5 public static void main (String[] args) { AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class ) ; ac.getBean(AppConfig.class ) ; }
而对于非懒加载的bean,getBean()的时候会从缓存里头取,因为容器初始化阶段已经初始化了。
初始化普通的单例bean 寻找bean实例化入口 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; }
在这里要注意区分bean实例化(第一步)和初始化(第三步)的区别:
实例化是指完成对象创建,此时它只是一个java对象,还没有完成和Spring有关的集成,也就是没有完成各种PostProcessors的洗礼;
初始化是指在完成实例化的同时,继而完成了各种与Spring容器集成等PostProcessors的处理,并且将其放入Spring的IOC容器中(本质上就是那个singletonMap)。
这里我们只关心第一步创建bean实例的流程:instanceWrapper = createBeanInstance(beanName, mbd, args);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 protected BeanWrapper createBeanInstance (String beanName, RootBeanDefinition mbd, @Nullable Object[] args) { Class<?> beanClass = resolveBeanClass(mbd, beanName); if (mbd.getFactoryMethodName() != null ) { return instantiateUsingFactoryMethod(beanName, mbd, args); } Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { return autowireConstructor(beanName, mbd, ctors, args); } return instantiateBean(beanName, mbd); }
这一步主要根据BeanDefinition里的元数据定义决定使用哪种实例化方法,主要有下面三种:
instantiateUsingFactoryMethod 工厂方法实例化的具体实现;
autowireConstructor 有参构造函数实例化的具体实现;
instantiateBean 默认实例化具体实现(无参构造函数)。
bean实例化策略 找到bean实例化入口后,我们来研究一下bean的实例化策略:
上面说到的两种实例化策略是根据BeanDefinition里的定义决定的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 protected BeanWrapper instantiateBean (final String beanName, final RootBeanDefinition mbd) { try { Object beanInstance; final BeanFactory parent = this ; if (System.getSecurityManager() != null ) { beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () -> getInstantiationStrategy().instantiate(mbd, beanName, parent), getAccessControlContext()); } else { beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent); } BeanWrapper bw = new BeanWrapperImpl(beanInstance); initBeanWrapper(bw); return bw; } catch (Throwable ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Instantiation of bean failed" , ex); } }
这里getInstantiationStrategy()会返回一种实例化策略,它们都是实现InstantiationStrategy接口的,该接口的实现类可以看到只有2种:
CglibSubclassingInstantiationStrategy:cglib策略;
SimpleInstantiationStrategy:简单反射策略。
然后真正调用实例化方法instantiate():
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 @Override public Object instantiate (RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) { if (!bd.hasMethodOverrides()) { Constructor<?> constructorToUse; synchronized (bd.constructorArgumentLock) { constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod; if (constructorToUse == null ) { final Class<?> clazz = bd.getBeanClass(); if (clazz.isInterface()) { throw new BeanInstantiationException(clazz, "Specified class is an interface" ); } try { if (System.getSecurityManager() != null ) { constructorToUse = AccessController.doPrivileged( (PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor); } else { constructorToUse = clazz.getDeclaredConstructor(); } bd.resolvedConstructorOrFactoryMethod = constructorToUse; } catch (Throwable ex) { throw new BeanInstantiationException(clazz, "No default constructor found" , ex); } } } return BeanUtils.instantiateClass(constructorToUse); } else { return instantiateWithMethodInjection(bd, beanName, owner); } }
总结 Bean实例化只是bean生命周期的一小部分,实际上只是bean初始化的一部分。
代码越读越薄。