注意,看完这篇文章需要很长很长很长时间。。。
本篇文章是SpringIOC源码解析(上)的续集,上一篇文章介绍了使用XML的方式启动Spring,然后追踪了BeanFactory容器的创建、配置文件的解析、Bean的注册等。
12. finishBeanFactoryInitialization()
前方超长篇幅预警。。。
刚才我们提到了bean还没有初始化。这个方法就是负责初始化所有的没有设置懒加载的singleton bean
开始撸了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) && ( beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) { beanFactory.setConversionService( beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)); } beanFactory.hasEmbeddedValueResolver()) { (! beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal)); } //先初始化 LoadTimeWeaverAware 类型的 Bean String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false); for (String weaverAwareName : weaverAwareNames) { getBean(weaverAwareName); } //停止使用用于类型匹配的临时类加载器 beanFactory.setTempClassLoader(null); //冻结所有的bean定义,即已注册的bean定义将不会被修改或后处理 beanFactory.freezeConfiguration(); //初始化 beanFactory.preInstantiateSingletons(); } |
上方没有解释的代码意义往下看吧
conversionService
这种类型的bean最实用的场景就是用来将前端传过来的参数和后端的controller方法上的参数格式转换的时候使用
例如:前端要传一个String,后端使用Date接受的时候就可以这样操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public class StringToDateConverter implements Converter<String, Date> { public Date convert(String date) { try { return dateFormat.parse(date); } catch (Exception e) { e.printStackTrace(); System.out.println("日期转换失败!"); return null; } } } |
再搞个bean
1 2 3 4 5 6 7 |
|
EmbeddedValueResolver
利用EmbeddedValueResolver可以很方便的实现读取配置文件的属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
public class PropertiesUtil implements EmbeddedValueResolverAware { private StringValueResolver resolver; public void setEmbeddedValueResolver(StringValueResolver resolver) { this.resolver = resolver; } /** * 获取属性时直接传入属性名称即可 */ public String getPropertiesValue(String key) { StringBuilder name = new StringBuilder("${").append(key).append("}"); return resolver.resolveStringValue(name.toString()); } } |
初始化
敲黑板了,重点来了。。。
这里分析beanFactory.preInstantiateSingletons()
方法
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 |
public void preInstantiateSingletons() throws BeansException { if (this.logger.isDebugEnabled()) { this.logger.debug("Pre-instantiating singletons in " + this); } // this.beanDefinitionNames 保存了所有的 beanNames List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames); for (String beanName : beanNames) { // 合并父 Bean 中的配置,主意 |
可以看到,不管是不是FactoryBean,最后都调用了getBean(beanName)
,继续看这个方法吧
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 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
@Override public Object getBean(String name) throws BeansException { return doGetBean(name, null, null, false); } protected |
看了上方方法我们知道了原来Spring本身只定义了两种Scope,也知道了SpringMVC的几种Scope是如何实现的了。
然后发现一开始会先判断bean存不存在,如果存在就直接返回了。如果不存在那就要接着往下看createBean
方法了
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 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException { if (logger.isDebugEnabled()) { logger.debug("Creating instance of bean '" + beanName + "'"); } RootBeanDefinition mbdToUse = mbd; // 确保 BeanDefinition 中的 Class 被加载 Class> resolvedClass = resolveBeanClass(mbd, beanName); if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) { mbdToUse = new RootBeanDefinition(mbd); mbdToUse.setBeanClass(resolvedClass); } // 准备方法覆写,如果bean中定义了 |
到这里第一次初始化的bean也返回了,你以为就这样结束了么。不,还有几个很重要的点
创建bean实例createBeanInstance ()
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 |
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) { // 确保已经加载了此 class 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()); } if (mbd.getFactoryMethodName() != null) { // 采用工厂方法实例化 return instantiateUsingFactoryMethod(beanName, mbd, args); } //是否第一次 boolean resolved = false; //是否采用构造函数注入 boolean autowireNecessary = false; if (args == null) { synchronized (mbd.constructorArgumentLock) { if (mbd.resolvedConstructorOrFactoryMethod != null) { resolved = true; autowireNecessary = mbd.constructorArgumentsResolved; } } } if (resolved) { if (autowireNecessary) { return autowireConstructor(beanName, mbd, null, null); } else { // 无参构造函数 return instantiateBean(beanName, mbd); } } // 判断是否采用有参构造函数 Constructor>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); if (ctors != null || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { // 构造函数依赖注入 return autowireConstructor(beanName, mbd, ctors, args); } // 调用无参构造函数 return instantiateBean(beanName, mbd); } |
选一个无参的构造看一下吧
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 |
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) { try { Object beanInstance; final BeanFactory parent = this; if (System.getSecurityManager() != null) { beanInstance = AccessController.doPrivileged(new PrivilegedAction public Object run() { return 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); } } public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) { // 如果不存在方法覆写,那就使用 java 反射进行实例化,否则使用 CGLIB, if (bd.getMethodOverrides().isEmpty()) { 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(new PrivilegedExceptionAction |
bean属性注入populateBean ()
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 |
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) { // bean的所有属性 PropertyValues pvs = mbd.getPropertyValues(); bw == null) { ( (!pvs.isEmpty()) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance"); } { return; } } boolean continueWithPropertyPopulation = true; (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { bp instanceof InstantiationAwareBeanPostProcessor) { ( InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; // 如果返回 false,代表不需要进行后续的属性设值,也不需要再经过其他的 BeanPostProcessor 的处理 bw.getWrappedInstance(), beanName)) { (!ibp.postProcessAfterInstantiation( continueWithPropertyPopulation = false; break; } } } } (!continueWithPropertyPopulation) { return; } || (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // 通过名字找到所有属性值,如果是 bean 依赖,先初始化依赖的 bean。记录依赖关系 (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // 通过类型装配。复杂一些 (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE); || needsDepCheck) { (hasInstAwareBpps PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); (hasInstAwareBpps) { for (BeanPostProcessor bp : getBeanPostProcessors()) { bp instanceof InstantiationAwareBeanPostProcessor) { ( InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; // 这里就是上方曾经提到过得对@Autowired处理的一个BeanPostProcessor了 // 它会对所有标记@Autowired、@Value 注解的属性进行设值 pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); (pvs == null) { return; } } } } (needsDepCheck) { checkDependencies(beanName, mbd, filteredPds, pvs); } } // 设置 bean 实例的属性值 applyPropertyValues(beanName, mbd, bw, pvs); } |
getBean这一块就搞完了
13. finishRefresh()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
protected void finishRefresh() { //看名字就知道了,清理刚才一系列操作使用到的资源缓存 clearResourceCaches(); // 初始化LifecycleProcessor initLifecycleProcessor(); // 这个方法的内部实现是启动所有实现了Lifecycle接口的bean getLifecycleProcessor().onRefresh(); //发布ContextRefreshedEvent事件 publishEvent(new ContextRefreshedEvent(this)); // 检查spring.liveBeansView.mbeanDomain是否存在,有就会创建一个MBeanServer LiveBeansView.registerApplicationContext(this); } |
14. resetCommonCaches()
最后还是一步还是清除缓存
15. refresh()
总结
上方用了这么长的篇幅把整个refresh()
方法的细节给梳理清楚,这里再把刚开始看的懵懵的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 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 |
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // 记录容器的启动时间、标记“已启动”状态、检查环境变量 prepareRefresh(); // 初始化BeanFactory容器、注册BeanDefinition ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean prepareBeanFactory(beanFactory); try { // 扩展点 postProcessBeanFactory(beanFactory); // 调用 BeanFactoryPostProcessor 各个实现类的 postProcessBeanFactory(factory) 方法 invokeBeanFactoryPostProcessors(beanFactory); // 注册 BeanPostProcessor 的实现类 registerBeanPostProcessors(beanFactory); // 初始化MessageSource initMessageSource(); // 初始化事件广播器 initApplicationEventMulticaster(); // 扩展点 onRefresh(); // 注册事件监听器 registerListeners(); // 初始化所有的 singleton beans finishBeanFactoryInitialization(beanFactory); // 广播事件 finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } // 销毁已经初始化的的Bean destroyBeans(); // 设置 'active' 状态 cancelRefresh(ex); throw ex; } finally { // 清除缓存 resetCommonCaches(); } } } |
总结
至此,本文到此结束。鉴于XML方式比较简单、通俗易懂,所以本文基于XML的方式大致介绍了SpringIOC的启动流程、稍微深入的讲解了Bean容器的创建以及Bean的初始化过程。这也是作者第一次阅读开源框架的源码,如文章有错误之处还请您费心指出。
鉴于现在比较流行SpringBoot和SpringCloud,下篇文章将会从基于注解的方向分析SpringIOC
推荐阅读
- SpringCloud学习系列汇总
- 为什么一线大厂面试必问redis,有啥好问的?
- 多线程面试必备基础知识汇总
- Java集合源码分析汇总-JDK1.8
- Linux常用命令速查-汇总篇
- JVM系列文章汇总
- MySQL系列文章汇总
- RabbitMQ系列文章汇总