Spring启动流程(基于xml)
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)throws BeansException {// 父类构造方法,最终实例化ResourcePatternResolversuper(parent);/** 1.实例环境属性* 2.设置配置文件路径(替换占位符)*/setConfigLocations(configLocations);// refreshif (refresh) {refresh();}}
1.构造ClassPathXmlApplicationContext

构造顺序
ClassPathXmlApplicationContext
-> super(AbstractXmlApplicationContext)
-> super(AbstractRefreshableConfigApplicationContext)
-> super(AbstractRefreshableApplicationContext)
-> super(AbstractApplicationContext)
// 最后实例ResourcePatternResolverpublic AbstractApplicationContext(@Nullable ApplicationContext parent) {this();setParent(parent);}this():public AbstractApplicationContext() {// 设置resourcePatternResolverthis.resourcePatternResolver = getResourcePatternResolver();}getResourcePatternResolver():protected ResourcePatternResolver getResourcePatternResolver() {return new PathMatchingResourcePatternResolver(this);}PathMatchingResourcePatternResolver(this):public PathMatchingResourcePatternResolver(ResourceLoader resourceLoader) {Assert.notNull(resourceLoader, "ResourceLoader must not be null");// 设置resourceLoaderthis.resourceLoader = resourceLoader;}
2.setConfigLocations(configLocations)
// 设置configLocationspublic void setConfigLocations(@Nullable String... locations) {// locations : 配置文件名称数组 例["applicationContext.xml",...]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;}}resolvePath(locations[i]).trim():protected String resolvePath(String path) {return getEnvironment().resolveRequiredPlaceholders(path);}
1.初始化环境变量

// 初始化环境变量 => 最终实例AbstractEnvironmentgetEnvironment:public ConfigurableEnvironment getEnvironment() {if (this.environment == null) {this.environment = createEnvironment();}return this.environment;}createEnvironment:protected ConfigurableEnvironment createEnvironment() {return new StandardEnvironment();}public StandardEnvironment() {}AbstractEnvironment():
2.解析占位符
resolveRequiredPlaceholders(path):public String resolveRequiredPlaceholders(String text) throws IllegalArgumentException {return this.propertyResolver.resolveRequiredPlaceholders(text);}resolveRequiredPlaceholders(text):public String resolveRequiredPlaceholders(String text) throws IllegalArgumentException {// 创建strictHelperif (this.strictHelper == null) {this.strictHelper = createPlaceholderHelper(false);}// 替换占位符return doResolvePlaceholders(text, this.strictHelper);}
1.创建占位符解析工具
createPlaceholderHelper(false):private PropertyPlaceholderHelper createPlaceholderHelper(boolean ignoreUnresolvablePlaceholders) {// this.placeholderPrefix = "${"// this.placeholderSuffix = "}"// this.valueSeparator = ":"// this.ignoreUnresolvablePlaceholders = falsereturn new PropertyPlaceholderHelper(this.placeholderPrefix, this.placeholderSuffix,this.valueSeparator, ignoreUnresolvablePlaceholders);}public PropertyPlaceholderHelper(String placeholderPrefix, String placeholderSuffix,@Nullable String valueSeparator, boolean ignoreUnresolvablePlaceholders) {Assert.notNull(placeholderPrefix, "'placeholderPrefix' must not be null");Assert.notNull(placeholderSuffix, "'placeholderSuffix' must not be null");// 设置开始符this.placeholderPrefix = placeholderPrefix;// 设置结束符this.placeholderSuffix = placeholderSuffix;// 设置配对符String simplePrefixForSuffix = wellKnownSimplePrefixes.get(this.placeholderSuffix);if (simplePrefixForSuffix != null && this.placeholderPrefix.endsWith(simplePrefixForSuffix)) {this.simplePrefix = simplePrefixForSuffix;}else {this.simplePrefix = this.placeholderPrefix;}// 设置分隔符this.valueSeparator = valueSeparator;// 设置是否忽略不可解析标志this.ignoreUnresolvablePlaceholders = ignoreUnresolvablePlaceholders;}
2.解析
doResolvePlaceholders:private String doResolvePlaceholders(String text, PropertyPlaceholderHelper helper) {return helper.replacePlaceholders(text, this::getPropertyAsRawString);}
- 获取属性
- propertySource.getProperty,不同propertySource执行器获取property值
- 判断是否需要占位符解析
- 转化value
- 判断是否需要转化
- 根据source,target类型获取转化执行器GenericConverter
- 转化
```java
this::getPropertyAsRawString:
protected String getPropertyAsRawString(String key) {
return getProperty(key, String.class, false);
}
protected
T getProperty(String key, Class targetValueType, boolean resolveNestedPlaceholders) { if (this.propertySources != null) { for (PropertySource<?> propertySource : this.propertySources) { // isTraceEnable => 记录日志 if (logger.isTraceEnabled()) {
} // 获取value : 策略模式 Object value = propertySource.getProperty(key); if (value != null) {logger.trace("Searching for key '" + key + "' in PropertySource '" +propertySource.getName() + "'");
} } } if (logger.isTraceEnabled()) { logger.trace(“Could not find key ‘“ + key + “‘ in any property source”); } return null; }if (resolveNestedPlaceholders && value instanceof String) {// value是否需要占位符解析 => resolveRequiredPlaceholders(...) 是:创建普通占位符解析工具 否:nonStrictHelper = nullvalue = resolveNestedPlaceholders((String) value);}// 记录key被找到logKeyFound(key, propertySource, value);// 转化valuereturn convertValueIfNecessary(value, targetValueType);
convertValueIfNecessary:
protected
isAssignableValue: public static boolean isAssignableValue(Class<?> type, @Nullable Object value) { Assert.notNull(type, “Type must not be null”); // 1.如果value不为空 = > isAssignable // 2.为空 => 是否 不是基本数据类型 return (value != null ? isAssignable(type, value.getClass()) : !type.isPrimitive()); }
isAssignable: public static boolean isAssignable(Class<?> lhsType, Class<?> rhsType) { Assert.notNull(lhsType, “Left-hand side type must not be null”); Assert.notNull(rhsType, “Right-hand side type must not be null”); // 存在继承关系或相同类,lhsType父类,rhsType子类 if (lhsType.isAssignableFrom(rhsType)) { return true; } // 基础数据类型 if (lhsType.isPrimitive()) { Class<?> resolvedPrimitive = primitiveWrapperTypeMap.get(rhsType); return (lhsType == resolvedPrimitive); } else { // 基本数据类型和对应数组 + void.class Class<?> resolvedWrapper = primitiveTypeToWrapperMap.get(rhsType); return (resolvedWrapper != null && lhsType.isAssignableFrom(resolvedWrapper)); } }
convert:
public
* desc不为空返回,为空new TypeDescriptor(new ResolvableType(clazz),null,null)* this.type = resolvableType.toClass*/return (desc != null ? desc : new TypeDescriptor(ResolvableType.forClass(type), null, null));
}
public Object convert(@Nullable Object source, @Nullable TypeDescriptor sourceType, TypeDescriptor targetType) { Assert.notNull(targetType, “Target type to convert to cannot be null”); if (sourceType == null) { Assert.isTrue(source == null, “Source must be [null] if source type == [null]”); return handleResult(null, targetType, convertNullSource(null, targetType)); } if (source != null && !sourceType.getObjectType().isInstance(source)) { throw new IllegalArgumentException(“Source to convert from must be an instance of [“ + sourceType + “]; instead it was a [“ + source.getClass().getName() + “]”); } // 根据两种类型 => 获取GenericConverter GenericConverter converter = getConverter(sourceType, targetType); if (converter != null) { // invokeConverter 转化 : 代理模式 Object result = ConversionUtils.invokeConverter(converter, source, sourceType, targetType); return handleResult(sourceType, targetType, result); } // 没找到GenericConverter return handleConverterNotFound(source, sourceType, targetType); }
2. 占位符解析```javaprotected String parseStringValue(String value, PlaceholderResolver placeholderResolver, @Nullable Set<String> visitedPlaceholders) {// 开始下标int startIndex = value.indexOf(this.placeholderPrefix);if (startIndex == -1) {return value;}// 结果StringBuilderStringBuilder result = new StringBuilder(value);while (startIndex != -1) {// 寻找结束下标int endIndex = findPlaceholderEndIndex(result, startIndex);if (endIndex != -1) {// 截取开始~结束部分 = placeholderString placeholder = result.substring(startIndex + this.placeholderPrefix.length(), endIndex);String originalPlaceholder = placeholder;if (visitedPlaceholders == null) {visitedPlaceholders = new HashSet<>(4);}// placeholder放入visitedPlaceholders,如果已经存在产生循环遍历if (!visitedPlaceholders.add(originalPlaceholder)) {throw new IllegalArgumentException("Circular placeholder reference '" + originalPlaceholder + "' in property definitions");}// 递归执行开始~结束部分,例:${${}}嵌套占位符情况placeholder = parseStringValue(placeholder, placeholderResolver, visitedPlaceholders);// 函数式接口 :: getPropertyAsRawString,获取属性String propVal = placeholderResolver.resolvePlaceholder(placeholder);// 获取解析属性 = null,解析分隔符前文本if (propVal == null && this.valueSeparator != null) {// 根据valueSeparator截取int separatorIndex = placeholder.indexOf(this.valueSeparator);if (separatorIndex != -1) {// : 前String actualPlaceholder = placeholder.substring(0, separatorIndex);// : 后 默认值String defaultValue = placeholder.substring(separatorIndex + this.valueSeparator.length());// 解析 :前的值 - null情况取默认值propVal = placeholderResolver.resolvePlaceholder(actualPlaceholder);if (propVal == null) {propVal = defaultValue;}}}if (propVal != null) {// 递归解析propVal = parseStringValue(propVal, placeholderResolver, visitedPlaceholders);result.replace(startIndex, endIndex + this.placeholderSuffix.length(), propVal);if (logger.isTraceEnabled()) {logger.trace("Resolved placeholder '" + placeholder + "'");}// 重置开始下标startIndex = result.indexOf(this.placeholderPrefix, startIndex + propVal.length());}else if (this.ignoreUnresolvablePlaceholders) {// 重置开始下标startIndex = result.indexOf(this.placeholderPrefix, endIndex + this.placeholderSuffix.length());}else {throw new IllegalArgumentException("Could not resolve placeholder '" +placeholder + "'" + " in value \"" + value + "\"");}// 移除originalPlaceholdervisitedPlaceholders.remove(originalPlaceholder);}else {// 找不到结束下标startIndex = -1;}}// 返回结果return result.toString();}
3.prepareRefresh
protected void prepareRefresh() {// 启动时间this.startupDate = System.currentTimeMillis();// 关闭状态this.closed.set(false);// 活跃状态this.active.set(true);// logif (logger.isDebugEnabled()) {if (logger.isTraceEnabled()) {logger.trace("Refreshing " + this);} else {logger.debug("Refreshing " + getDisplayName());}}// 扩展PropertySourcesinitPropertySources();// 验证requiredProperties是否都存在getEnvironment().validateRequiredProperties();// 实例化earlyApplicationif (this.earlyApplicationListeners == null) {this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);// 重置applicationListeners,[add]earlyApplicationListeners} else {this.applicationListeners.clear();this.applicationListeners.addAll(this.earlyApplicationListeners);}// 清空earlyApplicationEventsthis.earlyApplicationEvents = new LinkedHashSet<>();}
拓展initPropertySources重写即可
protected void initPropertySources() {// For subclasses: do nothing by default.}
validateRequiredProperties:@Overridepublic void validateRequiredProperties() {MissingRequiredPropertiesException ex = new MissingRequiredPropertiesException();for (String key : this.requiredProperties) {// 获取属性不为空addif (this.getProperty(key) == null) {ex.addMissingRequiredProperty(key);}}// ex有数据,抛出异常if (!ex.getMissingRequiredProperties().isEmpty()) {throw ex;}}
4.obtainFreshBeanFactory()
public final ConfigurableListableBeanFactory getBeanFactory() {DefaultListableBeanFactory beanFactory = this.beanFactory;if (beanFactory == null) {throw new IllegalStateException("BeanFactory not initialized or already closed - " +"call 'refresh' before accessing beans via the ApplicationContext");}return beanFactory;}
1.加载xml
2.解析xmlx
3.封装BeanDefinition
4.实例化
BeanDefinition -> 反射实例化
动态更改Bean信息 -> BeanFactoryPostProcessor -> … -> …
PostProcessor(后置处理器) -> 1.BeanFactoryPostProcessor -> 增强BeanDefinition信息
-> 2.BeanPostProcessor -> 增强Bean信息
实例化 -> 填充属性 -> 设置Aware接口属性(当创建Bean对象时候需要其他容器对象,实现Aware满足) -> 初始化 -> BeanPostProcessor.before -> initMethod -> BeanPostProcessor.after -> 完整对象
BeanFactory 和 FactoryBean
if(FactoryBean exist) => FactoryBean.create
else => 走BeanFactory流程实现
5.放入容器 - Map(三级缓存)
6.从容器中获取
