目录
1)、PropertyResolver(Property相关处理)
2)、Environment(Spring profiles相关处理)
3)、ConfigurablePropertyResolver(类型转换相关ConversionService)
SpringIoc源码,主要的核心是AbstractApplicationContext的refresh方法,所以一切还是回到ClassPathXMLApplicationContext开始
new ClassPathXmlApplicationContext("spring-bean.xml").getBean("kevin");
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh,
@Nullable ApplicationContext parent) throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
一般很少使用父ApplicationContext,所以忽略。 setConfigLocations方法
public void setConfigLocations(@Nullable 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;
}
}
循环处理每个location字符串,继续:
protected String resolvePath(String path) {
return getEnvironment().resolveRequiredPlaceholders(path);
}
在这里初始化了每个Spring容器的Environment,这个也是Spring Boot actuator的基础。
public ConfigurableEnvironment getEnvironment() {
if (this.environment == null) {
this.environment = createEnvironment();
}
return this.environment;
}
protected ConfigurableEnvironment createEnvironment() {
return new StandardEnvironment();
}
1、StandardEnvironment
个人觉得StandardEnvironment还是比较重要的,我们可以从中获取到很多开发时候需要的属性等。
1)、PropertyResolver(Property相关处理)
public interface PropertyResolver {
boolean containsProperty(String key);
@Nullable
String getProperty(String key);
String getProperty(String key, String defaultValue);
@Nullable
<T> T getProperty(String key, Class<T> targetType);
<T> T getProperty(String key, Class<T> targetType, T defaultValue);
String getRequiredProperty(String key) throws IllegalStateException;
<T> T getRequiredProperty(String key, Class<T> targetType) throws IllegalStateException;
String resolvePlaceholders(String text);
String resolveRequiredPlaceholders(String text) throws IllegalArgumentException;
}
2)、Environment(Spring profiles相关处理)
public interface Environment extends PropertyResolver {
String[] getActiveProfiles();
String[] getDefaultProfiles();
@Deprecated
boolean acceptsProfiles(String... profiles);
boolean acceptsProfiles(Profiles profiles);
}
3)、ConfigurablePropertyResolver(类型转换相关ConversionService)
比如很少时候,Date和字符串的转换,数字的转换等会使用比较多。
public interface ConfigurablePropertyResolver extends PropertyResolver {
ConfigurableConversionService getConversionService();
void setConversionService(ConfigurableConversionService conversionService);
void setPlaceholderPrefix(String placeholderPrefix);
void setPlaceholderSuffix(String placeholderSuffix);
void setValueSeparator(@Nullable String valueSeparator);
void setIgnoreUnresolvableNestedPlaceholders(boolean
ignoreUnresolvableNestedPlaceholders);
void setRequiredProperties(String... requiredProperties);
void validateRequiredProperties() throws MissingRequiredPropertiesException;
}
4)、ConfigurableEnvironment
public interface ConfigurableEnvironment extends Environment, ConfigurablePropertyResolver {
void setActiveProfiles(String... profiles);
void addActiveProfile(String profile);
void setDefaultProfiles(String... profiles);
MutablePropertySources getPropertySources();
Map<String, Object> getSystemProperties();
Map<String, Object> getSystemEnvironment();
// 设置父ApplicationContext时回调用
void merge(ConfigurableEnvironment parent);
}
5)、AbstractEnvironment
以上所有的接口声明基本都在AbstractEnvironment中完成,并且其的无参构造中回调了子类实现的customizePropertySources方法。
public abstract class AbstractEnvironment implements ConfigurableEnvironment {
public static final String IGNORE_GETENV_PROPERTY_NAME = "spring.getenv.ignore";
public static final String ACTIVE_PROFILES_PROPERTY_NAME = "spring.profiles.active";
public static final String DEFAULT_PROFILES_PROPERTY_NAME = "spring.profiles.default";
protected static final String RESERVED_DEFAULT_PROFILE_NAME = "default";
// 当前激活的profiles列表
private final Set<String> activeProfiles = new LinkedHashSet<>();
// 默认的profiles为RESERVED_DEFAULT_PROFILE_NAME(字符串 default)
private final Set<String> defaultProfiles = new LinkedHashSet<>(getReservedDefaultProfiles());
// 初始化MutablePropertySources类型
private final MutablePropertySources propertySources = new MutablePropertySources();
// 初始化PropertySourcesPropertyResolver类型
private final ConfigurablePropertyResolver propertyResolver =
new PropertySourcesPropertyResolver(this.propertySources);
public AbstractEnvironment() {
customizePropertySources(this.propertySources);
}
// 省略其他Property相关的方法等。
}
6)、StandardEnvironment
StandardEnvironment初始化,会父类无参构造,然后回调StandardEnvironment的customizePropertySources方法:
protected void customizePropertySources(MutablePropertySources propertySources) {
propertySources.addLast(new PropertiesPropertySource(
SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));
propertySources.addLast(new SystemEnvironmentPropertySource(
SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
}
将值回置到父类PropertySourcesPropertyResolver中的MutablePropertySources中。看看具体实现:
public Map<String, Object> getSystemProperties() {
return (Map) System.getProperties();
}
public Map<String, Object> getSystemEnvironment() {
return (Map) System.getenv();
}
都是从System中获取的,是java底层启动时就初始化完成的,只是Spring对其进行了包装。
2、refresh方法
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 准备环境
prepareRefresh();
// 初始化BeanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// BeanFactory初始化一些东西
prepareBeanFactory(beanFactory);
try {
// 模板方法允许当前AbstractApplicationContext子类,对BeanFactory进行一些改造
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
1)、prepareRefresh
protected void prepareRefresh() {
// Switch to active. 主要是实现Lifecycle接口的方法,容器生命周期相关
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
// 初始化容器的属性,主要是Web类型的ApplicationContext调用
// WebApplicationContextUtils#initServletPropertySources方法
initPropertySources();
// 验证属性信息会调用上面初始化的 AbstractEnvironment内部的
// PropertySourcesPropertyResolver#setRequiredProperties
getEnvironment().validateRequiredProperties();
// Store pre-refresh ApplicationListeners..., 这里基本都为空,不知道什么时候不为空,后续验证
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
else {
// Reset local application listeners to pre-refresh state.
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
this.earlyApplicationEvents = new LinkedHashSet<>();
}
之前是因为ClassPathXmlApplicatonContext类型,在refresh之前进行了setLocations,将StandardEnvironment(或其子类)初始化了,否则当前才会进行初始化。
2)、obtainFreshBeanFactory
初始化BeanFactory,主要看当前的ApplicationContext的类型,如果是AbstractRefreshableApplicationContext的子类和GenericApplicationContext的子类,实现会不相同。
protected final void refreshBeanFactory() throws BeansException {
// 如果beanFactory已经初始化了,则进行销毁
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
// 初始化BeanFactory -> new DefaultListableBeanFactory(getInternalParentBeanFactory());
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
// 留给子类实现
customizeBeanFactory(beanFactory);
// 加载BeanDefinition
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
// 省略
}
}
1、hasBeanFactory
判断比较简单(this.beanFactory != null),但是如果已经存在,则进行销毁。 之前写东西的时候,用到了相关的销毁,所以映象比较深,进行分析一下。
closeBeanFactory比较简单,将BeanFactory置为null,将id设置为空;
destroyBeans做了很多事,也更深入地理解了BeanFactory的允许机制,内部容器的结构。
protected void destroyBeans() {
getBeanFactory().destroySingletons();
}
当前的BeanFactory为DefaultListableBeanFactory,那么调用其方法
@Override
public void destroySingletons() {
super.destroySingletons();
updateManualSingletonNames(Set::clear, set -> !set.isEmpty());
clearByTypeCache();
}
分层的思想特别好,各处理各的容器(ConcurrentHashMap)。查看父类DefaultSingletonBeanRegistry的处理:
- 1)、DefaultSingletonBeanRegistry#destroySingletons
public void destroySingletons() {
synchronized (this.singletonObjects) {
this.singletonsCurrentlyInDestruction = true;
}
String[] disposableBeanNames;
synchronized (this.disposableBeans) {
disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet());
}
for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
destroySingleton(disposableBeanNames[i]);
}
this.containedBeanMap.clear();
this.dependentBeanMap.clear();
this.dependenciesForBeanMap.clear();
clearSingletonCache();
}
如果有实现了DisposableBean接口的,在当前进行销毁处理了很多地方(可想Spring设计的时候还是比较复杂的):
this.singletonObjects.remove(beanName);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.remove(beanName);
disposableBeans.remove(beanName);
dependentBeanMap.remove(beanName);
containedBeanMap.remove(beanName);
dependenciesForBeanMap.remove(beanName);
this.containedBeanMap.clear();
this.dependentBeanMap.clear();
this.dependenciesForBeanMap.clear();
this.singletonObjects.clear();
this.singletonFactories.clear();
this.earlySingletonObjects.clear();
this.registeredSingletons.clear();
this.singletonsCurrentlyInDestruction = false;
- 2)、DefaultListableBeanFactory#destroySingletons
this.allBeanNamesByType.clear();
this.singletonBeanNamesByType.clear();
2、createBeanFactory
protected DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}
比较简单,但是非常重要,做了很多事,详细参见:SpringIoc源码(二)- BeanFactory(一)- 结构梳理(DefaultListableBeanFactory)。
3、customizeBeanFactory
只有 AbstractRefreshableApplicationContext(以及其子类)有实现特殊定制:
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
if (this.allowBeanDefinitionOverriding != null) {
beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
if (this.allowCircularReferences != null) {
beanFactory.setAllowCircularReferences(this.allowCircularReferences);
}
}
4、loadBeanDefinitions
当前需要看是哪种类型的ApplicationContext,如果是Spring Boot的(GenericApplicationContext的子类)使用的都会进入到的方法:(只是设置id和检查)
protected final void refreshBeanFactory() throws IllegalStateException {
if (!this.refreshed.compareAndSet(false, true)) {
throw new IllegalStateException(
"GenericApplicationContext does not support multiple refresh attempts
: just call 'refresh' once");
}
this.beanFactory.setSerializationId(getId());
}
否则如果当前是AbstractRefreshableApplicationContext的子类,比如当前的ClassPathXmlApplicationContext类型:
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// Configure the bean definition reader with this context's
// resource loading environment.
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the bean definitions.
initBeanDefinitionReader(beanDefinitionReader);
loadBeanDefinitions(beanDefinitionReader);
}
比较熟悉了,new了一个XmlBeanDefinitionReader,再去
loadBeanDefinitions(beanDefinitionReader);
详细流程参见:SpringIoc源码(三)- BeanFactory(二)- XmlBeanFactory注册BeanDefinition