/* * Copyright (c) 2002-2012 Alibaba Group Holding Limited. * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.alibaba.citrus.service.moduleloader.impl.factory; import static com.alibaba.citrus.springext.util.DomUtil.*; import static com.alibaba.citrus.springext.util.SpringExtUtil.*; import static com.alibaba.citrus.util.Assert.*; import static com.alibaba.citrus.util.CollectionUtil.*; import static com.alibaba.citrus.util.StringUtil.*; import java.io.IOException; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.alibaba.citrus.service.moduleloader.impl.ModuleKey; import com.alibaba.citrus.springext.support.parser.AbstractNamedBeanDefinitionParser; import com.alibaba.citrus.springext.util.SpringExtUtil; import com.alibaba.citrus.util.regex.MatchResultSubstitution; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinitionHolder; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionDefaults; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.core.type.classreading.MetadataReader; import org.springframework.core.type.classreading.MetadataReaderFactory; import org.springframework.core.type.filter.TypeFilter; import org.w3c.dom.Element; public abstract class AbstractModuleFactoryDefinitionParser<T> extends AbstractNamedBeanDefinitionParser<T> { protected final Logger log = LoggerFactory.getLogger(getBeanClass(null)); /** 解析明确定义的beans,这些beans将覆盖自动搜索而得的module脚本。 */ protected final Map<String, ParsingModuleInfo> parseSpecificBeans(Element element, ParserContext parserContext, AbstractBeanDefinition containingBd, ElementSelector beanSelector) { Map<String, ParsingModuleInfo> specificBeans = createHashMap(); for (Element subElement : subElements(element, beanSelector)) { BeanDefinitionHolder bdh = (BeanDefinitionHolder) parserContext.getDelegate().parsePropertySubElement( subElement, containingBd); String itemName = parseItemName(parserContext, subElement, bdh.getBeanDefinition()); specificBeans.put(itemName, new ParsingModuleInfo(bdh.getBeanDefinition(), itemName)); } log.debug("Found {} specificly defined modules", specificBeans.size()); return specificBeans; } protected abstract String parseItemName(ParserContext parserContext, Element element, BeanDefinition bd); protected BeanDefinitionDefaults getBeanDefinitionDefaults(Element element, ParserContext parserContext) { BeanDefinitionDefaults defaults = new BeanDefinitionDefaults(); String defaultLazyInit = trimToNull(element.getAttribute("defaultLazyInit")); String defaultAutowireMode = trimToNull(element.getAttribute("defaultAutowireMode")); if (defaultLazyInit == null) { defaults.setLazyInit(getDefaultLazyInit()); } else { defaults.setLazyInit(Boolean.parseBoolean(defaultLazyInit)); } if (defaultAutowireMode == null) { defaultAutowireMode = getDefaultAutowireMode(); } defaults.setAutowireMode(parserContext.getDelegate().getAutowireMode(defaultAutowireMode)); return defaults; } protected boolean getDefaultLazyInit() { return false; } protected String getDefaultAutowireMode() { return "no"; } protected void postProcessItems(Element element, ParserContext parserContext, BeanDefinitionBuilder builder, Map<String, ParsingModuleInfo> items, String tags) { // 注册所有明确定义的beans for (ParsingModuleInfo item : items.values()) { if (item.bd != null) { assertNotNull(item.key, "Specificly-defined module could not be found in %s: %s", tags, item.itemName); item.beanName = SpringExtUtil.generateBeanName(item.getBaseBeanName(), parserContext.getRegistry()); parserContext.getRegistry().registerBeanDefinition(item.beanName, item.bd); } } // 设置ModuleFactory.setModules() List<Object> moduleList = createManagedList(element, parserContext); log.debug("Defined {} modules with {}", items.size(), getBeanClass(null).getSimpleName()); for (ParsingModuleInfo item : items.values()) { if (item.beanName != null) { BeanDefinitionBuilder bdb = BeanDefinitionBuilder.genericBeanDefinition(ModuleInfo.class); bdb.addConstructorArgValue(item.key); bdb.addConstructorArgValue(item.beanName); bdb.addConstructorArgValue(item.itemName); // className or script resourceName moduleList.add(bdb.getBeanDefinition()); log.debug("Defined module {} with {}", new Object[] { item.key, item.itemName }); } } builder.addPropertyValue("modules", moduleList); } /** 处理每一个匹配。 */ protected static class ParsingModuleMatcher { private final Map<String, ParsingModuleInfo> items; private final Pattern itemPattern; private final String typeName; private final String moduleName; private List<TypeFilter> includeFilters; public ParsingModuleMatcher(Map<String, ParsingModuleInfo> items, Pattern itemPattern, String typeName, String moduleName) { this(items, itemPattern, typeName, moduleName, null); } public ParsingModuleMatcher(Map<String, ParsingModuleInfo> items, Pattern itemPattern, String typeName, String moduleName, List<TypeFilter> includeFilters) { this.items = items; this.itemPattern = itemPattern; this.typeName = typeName; this.moduleName = moduleName; this.includeFilters = includeFilters; } protected boolean doMatch(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { String itemName = metadataReader.getAnnotationMetadata().getClassName(); Matcher matcher = itemPattern.matcher(itemName); if (!matcher.find()) { return false; } //根据用户提供的Filter来过滤当前扫瞄的元信息(属于二次过滤) boolean matched = true; if (this.includeFilters != null) { matched = this.includeFilters.size() < 1; for (TypeFilter filter : this.includeFilters) { if (matched) { break; } try { matched = filter.match(metadataReader, metadataReaderFactory); } catch (Exception e) { matched = false; } } } if (!matched) { return false; } return this.match(itemName, matcher); } protected final boolean doMatch(String itemName) { Matcher matcher = itemPattern.matcher(itemName); if (!matcher.find()) { return false; } return match(itemName, matcher); } private boolean match(String itemName, Matcher matcher) { MatchResultSubstitution subs = new MatchResultSubstitution(matcher); String type = trimToNull(subs.substitute(typeName)); String name; if (type == null) { return false; } if (moduleName == null) { int startIndex = subs.getMatch().end() + 1; if (itemName.length() > startIndex) { name = itemName.substring(startIndex); } else { return false; } } else { name = subs.substitute(moduleName); } name = getName(name, itemName); if (items.containsKey(itemName)) { ParsingModuleInfo item = items.get(itemName); // 对于特别创建的bean,补充其type和name信息。 if (item.bd != null && item.key == null) { item.key = new ModuleKey(type, name); } // 忽略重复匹配的类 return false; } else { items.put(itemName, new ParsingModuleInfo(type, name, itemName)); return true; } } protected String getName(String name, String itemName) { return name; } protected final String generateBeanName(String itemName, BeanDefinitionRegistry registry) { ParsingModuleInfo item = assertNotNull(items.get(itemName), "missing %s", itemName); item.beanName = SpringExtUtil.generateBeanName(item.getBaseBeanName(), registry); return item.beanName; } } /** 代表一个module的解析时信息。 */ protected static class ParsingModuleInfo { final BeanDefinition bd; final String itemName; String beanName; ModuleKey key; public ParsingModuleInfo(String moduleType, String moduleName, String itemName) { this.bd = null; this.key = new ModuleKey(moduleType, moduleName); this.itemName = itemName; } public ParsingModuleInfo(BeanDefinition bd, String itemName) { this.bd = bd; this.itemName = itemName; } public String getBaseBeanName() { return "module." + key.getModuleType() + "." + key.getModuleName(); } } }