Spring源码解读

 通过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;
		}		
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值