通过ClassPathXmlApplicationContext 作为整体的入口。
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException {
super(parent); // 调用父类的构造方法初始化相关属性
setConfigLocations(configLocations); // 将配置文件路径读入
if (refresh) {
refresh();
}
}
先看父类的构造方法,一路this点进去,获取解析需要的一些资源
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
// 创建上下文的唯一标识,id值为beanFactory使用
private String id = ObjectUtils.identityToString(this);
// 设置当前容器是否是激活状态
private final AtomicBoolean active = new AtomicBoolean();
// 设置当前容器是否是关闭状态
private final AtomicBoolean closed = new AtomicBoolean();
// 锁,为了refresh和destroy这两个过程 保证原子性
private final Object startupShutdownMonitor = new Object();
public AbstractApplicationContext() {
// 创建模式资源处理器,这里会直接初始化上面的资源
this.resourcePatternResolver = getResourcePatternResolver();
}
}
然后将路径配置读入
public void setConfigLocations(@Nullable String... locations) {
if (locations != 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;
}
}
这里是先去创建了一个环境对象
protected String resolvePath(String path) {
return getEnvironment().resolveRequiredPlaceholders(path);
}
-------------------------------------------------
@Override
public ConfigurableEnvironment getEnvironment() {
if (this.environment == null) {
// 第一次进来肯定没有,先去创建
this.environment = createEnvironment();
}
return this.environment;
}
-------------------------------------------------
protected ConfigurableEnvironment createEnvironment() {
return new StandardEnvironment();
}
由于StandardEnvironment 没有构造方法,所以得去看父类的构造方法
public AbstractEnvironment() {
customizePropertySources(this.propertySources); // 调用子类
}
父类的构造方法去调用子类重写的方法
public class StandardEnvironment extends AbstractEnvironment {
public static final String SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME = "systemEnvironment";
public static final String SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME = "systemProperties";
@Override
protected void customizePropertySources(MutablePropertySources propertySources) {
// 底层是用System.getProperties() 和 System.getenv() 获取相关属性进行填充
propertySources.addLast(
new PropertiesPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));
propertySources.addLast(
new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
}
}
这个时候环境已经创建完毕,现在去解析配置,具体在 AbstractPropertyResolver实现
@Override
public String resolveRequiredPlaceholders(String text) throws IllegalArgumentException {
if (this.strictHelper == null) {
this.strictHelper = createPlaceholderHelper(false);
}
return doResolvePlaceholders(text, this.strictHelper);
}
------------------------------------------------------
首先创建一个helper
private PropertyPlaceholderHelper createPlaceholderHelper(boolean ignoreUnresolvablePlaceholders) {
// 创建一个helper,前缀是"${" 后缀是 "}" 分隔符是 ":"
return new PropertyPlaceholderHelper(this.placeholderPrefix, this.placeholderSuffix, this.valueSeparator, ignoreUnresolvablePlaceholders);
}
------------------------------------------------------
然后去解析
private String doResolvePlaceholders(String text, PropertyPlaceholderHelper helper) {
return helper.replacePlaceholders(text, this::getPropertyAsRawString);
}
------------------------------------------------------
public String replacePlaceholders(String value, PlaceholderResolver placeholderResolver) {
return parseStringValue(value, placeholderResolver, null);
}
-----------------------------------------------------
protected String parseStringValue( String value, PropertyPlaceholderHelper.PlaceholderResolver placeholderResolver, @Nullable Set<String> visitedPlaceholders) {
// 先去定位前缀的index
int startIndex = value.indexOf(this.placeholderPrefix);
StringBuilder result = new StringBuilder(value);
while (startIndex != -1) {
// 找到最后一个后缀的位置
int endIndex = findPlaceholderEndIndex(result, startIndex);
if (endIndex != -1) {
String placeholder = result.substring(startIndex + this.placeholderPrefix.length(), endIndex);
String originalPlaceholder = placeholder;
// 递归调用 以防出现套娃的形式
placeholder = parseStringValue(placeholder, placeholderResolver, visitedPlaceholders);
// 找到替换值,这里执行的是传入的lambda表达式
String propVal = placeholderResolver.resolvePlaceholder(placeholder);
if (propVal != null) {
propVal = parseStringValue(propVal, placeholderResolver, visitedPlaceholders);
// 直接进行替换
result.replace(startIndex, endIndex + this.placeholderSuffix.length(), propVal);
startIndex = result.indexOf(this.placeholderPrefix, startIndex + propVal.length());
}
else if (this.ignoreUnresolvablePlaceholders) {
startIndex = result.indexOf(this.placeholderPrefix, endIndex + this.placeholderSuffix.length());
}
// 删除已经替换的
visitedPlaceholders.remove(originalPlaceholder);
}
}
return result.toString();
}
通过在系统环境中进行替换值的查找,到这里前期的准备工作完毕。
@Override
protected String getPropertyAsRawString(String key) {
return getProperty(key, String.class, false);
}
protected <T> T getProperty(String key, Class<T> targetValueType, boolean resolveNestedPlaceholders) {
if (this.propertySources != null) {
for (PropertySource<?> propertySource : this.propertySources) {
Object value = propertySource.getProperty(key);
if (value != null) {
if (resolveNestedPlaceholders && value instanceof String) {
value = resolveNestedPlaceholders((String) value);
}
logKeyFound(key, propertySource, value);
return convertValueIfNecessary(value, targetValueType);
}
}
}
return null;
}
然后看主要的refresh方法。
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 前戏准备工作
prepareRefresh();
// 创建容器对象,最重要的是完成了beanDefinition
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 设置一些属性值
prepareBeanFactory(beanFactory);
try {
// 是一个空方法,留给子类进行扩展
postProcessBeanFactory(beanFactory);
// 调用各种beanFactory处理器
invokeBeanFactoryPostProcessors(beanFactory);
// 准备beanPostProcesser 和 监听器等,这里只是注册
registerBeanPostProcessors(beanFactory);
// 为上下文初始化message源,主要做国际化
initMessageSource();
// 初始化事件监听多路广播器
initApplicationEventMulticaster();
// 空方法,留给子类进行实现
onRefresh();
// 在所有注册的bean中查找listener bean,注册到消息广播器中
registerListeners();
// 实例化所有单例对象(不是懒加载的bean)
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
}
}
第一步,前戏准备工作,主要是初始化一些必要的值。
protected void prepareRefresh() {
this.startupDate = System.currentTimeMillis(); // 设置启动时间
this.closed.set(false); // 设置状态开启关闭的标志
this.active.set(true);
initPropertySources(); // 这是一个空方法,留给我们自定义
getEnvironment().validateRequiredProperties(); // 验证是否所有的变量是否合法
// 初始化监听器
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
else {
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
this.earlyApplicationEvents = new LinkedHashSet<>();
}
第二步,创建容器对象,主要是创建完成了beanDefinition,加载配置文件和解析工作。
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory(); // 初始化beanFactory,并从配置文件或注解读取配置
return getBeanFactory(); // 返回当前beanFactory属性
}
---------------------------------------------------
@Override
protected final void refreshBeanFactory() throws BeansException {
// 如果有beanFactory,则销毁
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
// 创建DefaultListableBeanFactory ,底层直接去new了
DefaultListableBeanFactory beanFactory = createBeanFactory();
// 为了序列化指定id
beanFactory.setSerializationId(getId());
// 设置是否允许同名不同定义的对象,以及循环依赖
customizeBeanFactory(beanFactory);
// 从配置文件或者注解读取配置,这里套娃开始
loadBeanDefinitions(beanFactory);
this.beanFactory = beanFactory;
}
}
看看如何从xml读取文件配置信息
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// 创建一个专门读取xml的读取器
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// 把一些环境变量设置给beanDefinitionReader方便进行值的替换
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
// 读取本地的xsd或者dtd文件 来解析
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
initBeanDefinitionReader(beanDefinitionReader);
// 从xml加载bean的信息
loadBeanDefinitions(beanDefinitionReader);
}
我们看看如何从xml加载的信息,这里有许多的loadBeanDefinitions的重载方法,不过禁止套娃!!!
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
... // 代码省略
String[] configLocations = getConfigLocations();
if (configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
}
----------------------------------------------------------------
@Override
public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
int count = 0;
for (String location : locations) {
count += loadBeanDefinitions(location);
}
return count;
}
---------------------------------------------------------------
@Override
public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
return loadBeanDefinitions(location, null);
}
---------------------------------------------------------------
public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
ResourceLoader resourceLoader = getResourceLoader();
// 判断是不是这个子类,肯定是这个子类
// 因为ResourcePatternResolver是 AnnoationConfigApplicationContext 顶级父类实现的接口
if (resourceLoader instanceof ResourcePatternResolver) {
Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
// 加载beanDefinition
int count = loadBeanDefinitions(resources);
if (actualResources != null) {
Collections.addAll(actualResources, resources);
}
return count;
}
else {
Resource resource = resourceLoader.getResource(location);
int count = loadBeanDefinitions(resource);
if (actualResources != null) {
actualResources.add(resource);
}
return count;
}
}
通过 getResources 去获取的内容,最后返回的是resource数组
@Override
public Resource[] getResources(String locationPattern) throws IOException {
// 如果 configLocatin 以 “classpath*:” 开头
if (locationPattern.startsWith(CLASSPATH_ALL_URL_PREFIX)) {
if (getPathMatcher().isPattern(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()))) {
return findPathMatchingResources(locationPattern);
}
else {
return findAllClassPathResources(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()));
}
}
else {
int prefixEnd = (locationPattern.startsWith("war:") ? locationPattern.indexOf("*/") + 1 :
locationPattern.indexOf(':') + 1);
// 配置文件是不是"war:"开头
if (getPathMatcher().isPattern(locationPattern.substring(prefixEnd))) {
return findPathMatchingResources(locationPattern);
}
else {
return new Resource[] {getResourceLoader().getResource(locationPattern)};
}
}
}
来看加载bean的信息
@Override
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
int count = 0;
for (Resource resource : resources) {
count += loadBeanDefinitions(resource);
}
return count;
}
-----------------------------------------------------------
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
return loadBeanDefinitions(new EncodedResource(resource));
}
-----------------------------------------------------------
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
// 获取当前已经加载过的资源
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
try (InputStream inputStream = encodedResource.getResource().getInputStream()) {
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
// 核心加载方法
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
finally {
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
}
}
-----------------------------------------------------------
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {
// 将输入流转换成文档对象
Document doc = doLoadDocument(inputSource, resource);
// 注册bean
int count = registerBeanDefinitions(doc, resource);
return count;
}
转换成文档对象
protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
// getValidationModeForResource 获取文件的格式
// 然后在这里去解析出来
return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,getValidationModeForResource(resource), isNamespaceAware());
}
----------------------------------------------------------------
protected int getValidationModeForResource(Resource resource) {
int validationModeToUse = getValidationMode();
if (validationModeToUse != VALIDATION_AUTO) {
return validationModeToUse;
}
int detectedMode = detectValidationMode(resource);
if (detectedMode != VALIDATION_AUTO) {
return detectedMode;
}
return VALIDATION_XSD;
}
-----------------------------------------------------------------
protected int detectValidationMode(Resource resource) {
return this.validationModeDetector.detectValidationMode(inputStream);
}
-----------------------------------------------------------------
public int detectValidationMode(InputStream inputStream) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
boolean isDtdValidated = false;
String content;
while ((content = reader.readLine()) != null) {
content = consumeCommentTokens(content);
if (this.inComment || !StringUtils.hasText(content)) {
continue;
}
if (hasDoctype(content)) {
isDtdValidated = true;
break;
}
if (hasOpeningTag(content)) {
break;
}
}
// 真正是在这里决定返回的格式
return (isDtdValidated ? VALIDATION_DTD : VALIDATION_XSD);
}
回过头继续看注册bean
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
int countBefore = getRegistry().getBeanDefinitionCount();
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}
------------------------------------------------------------
@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
doRegisterBeanDefinitions(doc.getDocumentElement()); // 真正解析的地方
}
------------------------------------------------------------
protected void doRegisterBeanDefinitions(Element root) {
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createDelegate(getReaderContext(), root, parent);
... // 代码省略
preProcessXml(root); // 空方法 对xml的前置处理
parseBeanDefinitions(root, this.delegate); // 解析的地方
postProcessXml(root); // 空方法 对xml的后置处理
this.delegate = parent;
}
-------------------------------------------------------------
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
// 如果节点是默认的命名空间的
if (delegate.isDefaultNamespace(ele)) {
parseDefaultElement(ele, delegate);
}
else {
delegate.parseCustomElement(ele);
}
}
}
}
else {
// 进行自定义标签的解析
delegate.parseCustomElement(root);
}
}
这里会进行一些标签的匹配,以及详细的解析bean标签的属性。
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) { // 匹配到import标签
importBeanDefinitionResource(ele);
}
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) { // 匹配到alias标签
processAliasRegistration(ele);
}
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) { // 匹配到bean标签,主要看bean
processBeanDefinition(ele, delegate);
}
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) { // 匹配到其他标签
doRegisterBeanDefinitions(ele);
}
}
--------------------------------------------------------------
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
// 这里将beanDefinition 放到map里面
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
--------------------------------------------------------------
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
// 获取节点的id和name
String id = ele.getAttribute(ID_ATTRIBUTE);
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
// 别名相关的操作
List<String> aliases = new ArrayList<>();
if (StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
aliases.addAll(Arrays.asList(nameArr));
}
// 验证是否有重复的bean
if (containingBean == null) {
checkNameUniqueness(beanName, aliases, ele);
}
// 这里对bean进行详细的解析
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
if (!StringUtils.hasText(beanName)) {
try {
if (containingBean != null) {
beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
}
else {
beanName = this.readerContext.generateBeanName(beanDefinition);
String beanClassName = beanDefinition.getBeanClassName();
if (beanClassName != null &&
beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() && !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
aliases.add(beanClassName);
}
}
}
}
String[] aliasesArray = StringUtils.toStringArray(aliases);
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
return null;
}
去看对bean 的详细解析,主要是将xml所有的信息解析到beanDefinition。
public AbstractBeanDefinition parseBeanDefinitionElement(
Element ele, String beanName, @Nullable BeanDefinition containingBean) {
... // 代码省略
// 创建beanDefinition 底层是去new GenericBeanDefinition
AbstractBeanDefinition bd = createBeanDefinition(className, parent);
// 往后就是解析bean 的定义信息
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
parseMetaElements(ele, bd);
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
parseConstructorArgElements(ele, bd); // 解析构造方法
parsePropertyElements(ele, bd);
parseQualifierElements(ele, bd);
bd.setResource(this.readerContext.getResource());
bd.setSource(extractSource(ele));
return bd;
}
然后继续看将beanDefinition放到 map中的操作
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
String beanName = definitionHolder.getBeanName();
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
}
------------------------------------------------------------
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {
// 如果已经存在相同的beanName并且允许覆盖的话,那就可以进行覆盖
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
if (hasBeanCreationStarted()) {
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
removeManualSingletonName(beanName);
}
}
else {
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
}
现在看一下如何进行自定义标签的解析
public BeanDefinition parseCustomElement(Element ele) {
return parseCustomElement(ele, null);
}
------------------------------------------------------------
public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
String namespaceUri = getNamespaceURI(ele);
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
-------------------------------------------------------------
@Override
public NamespaceHandler resolve(String namespaceUri) {
// 获取spring中所有jar包的 META-INF/spring.handlers 文件 并建立映射关系
// 底层是去 new DefaultNamespaceHandlerResolver 这个类的时候将"META-INF/spring.handlers"作为参数传入
// 所有配置文件的类都是实现了namespaceHandler这个接口
Map<String, Object> handlerMappings = getHandlerMappings();
Object handlerOrClassName = handlerMappings.get(namespaceUri);
if (handlerOrClassName == null) {
return null;
}
else if (handlerOrClassName instanceof NamespaceHandler) {
return (NamespaceHandler) handlerOrClassName;
}
else {
String className = (String) handlerOrClassName;
try {
// 通过反射拿到处理类
Class<?> handlerClass = ClassUtils.forName(className, this.classLoader);
// 实例化
NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);
// 完成标签元素解析的类注册
namespaceHandler.init();
handlerMappings.put(namespaceUri, namespaceHandler);
return namespaceHandler;
}
}
}