准备 Person实例
1 2 3 4 5 @Data public class Person { private String name; private int age; }
xml bean配置
1 2 3 4 5 6 7 8 9 10 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns ="http://www.springframework.org/schema/beans" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xmlns:context ="http://www.springframework.org/schema/context" xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd" > <bean id ="person" class ="com.gcdd1993.spring.framework.base.domain.Person" /> </beans >
入口
1 2 AbstractApplicationContext applicationContext = new ClassPathXmlApplicationContext("config.xml" ); applicationContext.getBean("person" );
使用Debug进入ClassPathXmlApplicationContext
构造函数,源码如下
1 2 3 4 5 6 7 8 9 public ClassPathXmlApplicationContext (String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException { super (parent); setConfigLocations(configLocations); if (refresh) { refresh(); } }
super(parent) 一步步向上调用父类构造函数,路径为
ClassPathXmlApplicationContext -> AbstractXmlApplicationContext -> AbstractRefreshableConfigApplicationContext -> AbstractRefreshableApplicationContext -> AbstractApplicationContext
历经整个继承体系,最终到达AbstractApplicationContext
:
1 2 3 4 public AbstractApplicationContext (ApplicationContext parent) { this (); setParent(parent); }
最后会设置当前ApplicationContext
的父级ApplicationContext
setConfigLocations(configLocations) 设置配置文件路径,解析的细节参照官方文档Resource一节,不是本文讨论的重点,在此略过。
1 2 3 4 5 6 7 8 9 10 11 12 public void setConfigLocations (String... locations) { if (locations != null ) { Assert.noNullElements(locations, "Config locations must not be null" ); this .configLocations = new String[locations.length]; for (int i = 0 ; i < locations.length; i++) { this .configLocations[i] = resolvePath(locations[i]).trim(); } } else { this .configLocations = null ; } }
refresh() 此方法是Spring容器的核心方法,源码(精简了try catch部分)如下:
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 public void refresh () throws BeansException, IllegalStateException { prepareRefresh(); ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); prepareBeanFactory(beanFactory); postProcessBeanFactory(beanFactory); invokeBeanFactoryPostProcessors(beanFactory); registerBeanPostProcessors(beanFactory); initMessageSource(); initApplicationEventMulticaster(); onRefresh(); registerListeners(); finishBeanFactoryInitialization(beanFactory); finishRefresh(); }
此处可以看到Spring编码方式近似于流程图的,重点部分都抽出为了单独的方法,流程清晰,易于理解。我们一步步看:
prepareRefresh()
上下文刷新前预热
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 protected void prepareRefresh () { this .startupDate = System.currentTimeMillis(); this .closed.set(false ); this .active.set(true ); if (logger.isInfoEnabled()) { logger.info("Refreshing " + this ); } initPropertySources(); getEnvironment().validateRequiredProperties(); this .earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>(); }
设置上下文基本信息,如startupDate(启动时刻)、closed(是否关闭)、active(是否存活)等等。
解析占位符资源,并验证标记为required的资源是否可用
obtainFreshBeanFactory()
初始化beanFactory(bean工厂,实际存放bean的就是它了)
1 2 3 4 5 6 7 8 protected ConfigurableListableBeanFactory obtainFreshBeanFactory () { refreshBeanFactory(); ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (logger.isDebugEnabled()) { logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory); } return beanFactory; }
核心方法refreshBeanFactory()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 protected final void refreshBeanFactory () throws BeansException { if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try { DefaultListableBeanFactory beanFactory = createBeanFactory(); beanFactory.setSerializationId(getId()); customizeBeanFactory(beanFactory); loadBeanDefinitions(beanFactory); synchronized (this .beanFactoryMonitor) { this .beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } }
createBeanFactory();
设置beanFactory属性
loadBeanDefinitions(beanFactory);
loadBeanDefinitions(beanFactory)
解析bean定义,有几个bean就有几个BeanDefinition。注意,Spring并不是拿到配置就直接用反射实例化bean,而是先将bean配置解析为BeanDefinition。
BeanDefinition保存了实例化bean需要的一切信息,包括属性,依赖等。以ConcurrentHashMap<String, BeanDefinition>
保存在DefaultListableBeanFactory的beanDefinitionMap里。
prepareBeanFactory(beanFactory)
设置beanFactory的其余属性
postProcessBeanFactory(beanFactory)
空实现,给子类一个机会,自定义beanFactory后置处理器
BeanFactoryPostProcessor
定义:
1 2 3 4 5 public interface BeanFactoryPostProcessor { void postProcessBeanFactory (ConfigurableListableBeanFactory beanFactory) throws BeansException ; }
invokeBeanFactoryPostProcessors(beanFactory)
执行上一步中的beanFactory后置处理器的回调方法void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
registerBeanPostProcessors(beanFactory)
注册bean后置处理器,实现bean初始化前后的自定义逻辑
BeanPostProcessor
定义:
1 2 3 4 5 6 public interface BeanPostProcessor { Object postProcessBeforeInitialization (Object bean, String beanName) throws BeansException ; Object postProcessAfterInitialization (Object bean, String beanName) throws BeansException ; }
initMessageSource()
注册国际化相关bean
initApplicationEventMulticaster()
初始化Spring事件发布相关bean
onRefresh()
空实现,给子类一个机会,初始化特殊bean
registerListeners()
注册监听器
finishBeanFactoryInitialization(beanFactory)
实例化所有非懒加载的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 protected void finishBeanFactoryInitialization (ConfigurableListableBeanFactory beanFactory) { if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) && beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) { beanFactory.setConversionService( beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)); } if (!beanFactory.hasEmbeddedValueResolver()) { beanFactory.addEmbeddedValueResolver(new StringValueResolver() { @Override public String resolveStringValue (String strVal) { return getEnvironment().resolvePlaceholders(strVal); } }); } String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false , false ); for (String weaverAwareName : weaverAwareNames) { getBean(weaverAwareName); } beanFactory.setTempClassLoader(null ); beanFactory.freezeConfiguration(); beanFactory.preInstantiateSingletons(); }
preInstantiateSingletons()
根据每一个bean定义,实例化bean
为每一个实现SmartInitializingSingleton的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 for (String beanName : beanNames) { RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { if (isFactoryBean(beanName)) { final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName); boolean isEagerInit; if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() { @Override public Boolean run () { return ((SmartFactoryBean<?>) factory).isEagerInit(); } }, getAccessControlContext()); } else { isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factory).isEagerInit()); } if (isEagerInit) { getBean(beanName); } } else { getBean(beanName); } } }
getBean(String name) 该方法调用了一个doGetBean,doGetBean代码较长,而且有部分代码是为了解决并发场景下单例的生成,我们挑出重点的看:
从父BeanFactory检查是否存在该bean的定义,如果存在,委托父BeanFactory来实例化
1 2 3 4 5 6 7 8 9 10 11 12 13 BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { String nameToLookup = originalBeanName(name); if (args != null ) { return (T) parentBeanFactory.getBean(nameToLookup, args); } else { return parentBeanFactory.getBean(nameToLookup, requiredType); } }
获得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 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);checkMergedBeanDefinition(mbd, beanName, args); String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null ) { for (String dep : dependsOn) { if (isDependent(beanName, dep)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'" ); } registerDependentBean(dep, beanName); try { getBean(dep); } catch (NoSuchBeanDefinitionException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'" , ex); } } }
实例化bean
方法调用流程:
createBean > doCreateBean > populateBean
其中doCreateBean:
从BeanDefinition生成BeanWrapper
将BeanWrapper和BeanDefinition.getPropertyValues() 传给populateBean,实例化bean
finishRefresh() 1 2 3 4 5 6 7 8 9 10 11 12 13 protected void finishRefresh () { initLifecycleProcessor(); getLifecycleProcessor().onRefresh(); publishEvent(new ContextRefreshedEvent(this )); LiveBeansView.registerApplicationContext(this ); }
总结 Spring IoC Container时序图