motan源碼分析三:與spring框架的結合

motan源碼分析三:與spring框架的結合

在本文第一章,分析的demo中使用了代碼加載的方式加載了相關的類,但在我們的實際工作中,使用spring來加載相關的類的情況會更多,本文將分析一下motan是如何與spring一起協同工作的,主要的原理就是利用了spring支持的自定義標籤的實現,這也是需要和spring結合的框架的實現方式。

1.首先實現motan.xsd文件,具體可以參見:http://api.weibo.com/schema/motan.xsd

2.對於標籤的相應解析類進行註冊:

public class MotanNamespaceHandler extends NamespaceHandlerSupport {//集成NamespaceHandlerSupport類,spring會自動調用init方法
public final static Set<string> protocolDefineNames = new ConcurrentHashSet<string>();
public final static Set<string> registryDefineNames = new ConcurrentHashSet<string>();
public final static Set<string> basicServiceConfigDefineNames = new ConcurrentHashSet<string>();
public final static Set<string> basicRefererConfigDefineNames = new ConcurrentHashSet<string>();
@Override
public void init() {//標記註冊
registerBeanDefinitionParser("referer", new MotanBeanDefinitionParser(RefererConfigBean.class, false));
registerBeanDefinitionParser("service", new MotanBeanDefinitionParser(ServiceConfigBean.class, true));
registerBeanDefinitionParser("protocol", new MotanBeanDefinitionParser(ProtocolConfig.class, true));
registerBeanDefinitionParser("registry", new MotanBeanDefinitionParser(RegistryConfig.class, true));
registerBeanDefinitionParser("basicService", new MotanBeanDefinitionParser(BasicServiceInterfaceConfig.class, true));
registerBeanDefinitionParser("basicReferer", new MotanBeanDefinitionParser(BasicRefererInterfaceConfig.class, true));
registerBeanDefinitionParser("spi", new MotanBeanDefinitionParser(SpiConfigBean.class, true));
registerBeanDefinitionParser("annotation", new MotanBeanDefinitionParser(AnnotationBean.class, true));
Initializable initialization = InitializationFactory.getInitialization();
initialization.init();
}
}
/<string>/<string>/<string>/<string>/<string>/<string>/<string>/<string>

3.motan的標籤解析類MotanBeanDefinitionParser:

public class MotanBeanDefinitionParser implements BeanDefinitionParser {//實現BeanDefinitionParser接口
private final Class> beanClass;
private final boolean required;

public MotanBeanDefinitionParser(Class> beanClass, boolean required) {
this.beanClass = beanClass;
this.required = required;
}
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
try {
return parse(element, parserContext, beanClass, required);
} catch (ClassNotFoundException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
@SuppressWarnings({"rawtypes", "unchecked"})
private static BeanDefinition parse(Element element, ParserContext parserContext, Class> beanClass, boolean required)
throws ClassNotFoundException {
RootBeanDefinition bd = new RootBeanDefinition();
bd.setBeanClass(beanClass);
// 不允許lazy init
bd.setLazyInit(false);
// 如果沒有id則按照規則生成一個id,註冊id到context中
String id = element.getAttribute("id");
if ((id == null || id.length() == 0) && required) {
String generatedBeanName = element.getAttribute("name");
if (generatedBeanName == null || generatedBeanName.length() == 0) {
generatedBeanName = element.getAttribute("class");
}
if (generatedBeanName == null || generatedBeanName.length() == 0) {
generatedBeanName = beanClass.getName();
}
id = generatedBeanName;
int counter = 2;
while (parserContext.getRegistry().containsBeanDefinition(id)) {
id = generatedBeanName + (counter++);
}
}
if (id != null && id.length() > 0) {
if (parserContext.getRegistry().containsBeanDefinition(id)) {
throw new IllegalStateException("Duplicate spring bean id " + id);
}
parserContext.getRegistry().registerBeanDefinition(id, bd);
}
bd.getPropertyValues().addPropertyValue("id", id);
if (ProtocolConfig.class.equals(beanClass)) {
MotanNamespaceHandler.protocolDefineNames.add(id);
} else if (RegistryConfig.class.equals(beanClass)) {
MotanNamespaceHandler.registryDefineNames.add(id);
} else if (BasicServiceInterfaceConfig.class.equals(beanClass)) {

MotanNamespaceHandler.basicServiceConfigDefineNames.add(id);
} else if (BasicRefererInterfaceConfig.class.equals(beanClass)) {
MotanNamespaceHandler.basicRefererConfigDefineNames.add(id);
} else if (ServiceConfigBean.class.equals(beanClass)) {
String className = element.getAttribute("class");
if (className != null && className.length() > 0) {
RootBeanDefinition classDefinition = new RootBeanDefinition();
classDefinition.setBeanClass(Class.forName(className, true, Thread.currentThread().getContextClassLoader()));
classDefinition.setLazyInit(false);
parseProperties(element.getChildNodes(), classDefinition);
bd.getPropertyValues().addPropertyValue("ref", new BeanDefinitionHolder(classDefinition, id + "Impl"));
}
}
Set<string> props = new HashSet<string>();
ManagedMap parameters = null;
// 把配置文件中的可以set的屬性放到bd中
for (Method setter : beanClass.getMethods()) {
String name = setter.getName();
// 必須是setXXX
if (name.length() <= 3 || !name.startsWith("set") || !Modifier.isPublic(setter.getModifiers())
|| setter.getParameterTypes().length != 1) {
continue;
}
String property = (name.substring(3, 4).toLowerCase() + name.substring(4)).replaceAll("_", "-");
props.add(property);
if ("id".equals(property)) {
bd.getPropertyValues().addPropertyValue("id", id);
continue;
}
String value = element.getAttribute(property);
if (StringUtils.isBlank(value) && "protocol".equals(property)) {
// srevice中的protocol信息是隱含在export中,所以需要從export中獲取protocol來配置
String exportValue = element.getAttribute(URLParamType.export.getName());
if (!StringUtils.isBlank(exportValue)) {
value = ConfigUtil.extractProtocols(exportValue);
}
}
if ("methods".equals(property)) {
parseMethods(id, element.getChildNodes(), bd, parserContext);
}
if (StringUtils.isBlank(value)) {
continue;
}
value = value.trim();
if (value.length() == 0) {
continue;
}

Object reference;
if ("ref".equals(property)) {
if (parserContext.getRegistry().containsBeanDefinition(value)) {
BeanDefinition refBean = parserContext.getRegistry().getBeanDefinition(value);
if (!refBean.isSingleton()) {
throw new IllegalStateException("The exported service ref " + value + " must be singleton! Please set the " + value
+ " bean scope to singleton, eg: <bean>");
}
}
reference = new RuntimeBeanReference(value);
} else if ("protocol".equals(property)) {
if (!value.contains(",")) {
reference = new RuntimeBeanReference(value);
} else {
parseMultiRef("protocols", value, bd, parserContext);
reference = null;
}
} else if ("registry".equals(property)) {
parseMultiRef("registries", value, bd, parserContext);
reference = null;
} else if ("basicService".equals(property)) {
reference = new RuntimeBeanReference(value);
} else if ("basicReferer".equals(property)) {
reference = new RuntimeBeanReference(value);
} else if ("extConfig".equals(property)) {
reference = new RuntimeBeanReference(value);
} else {
reference = new TypedStringValue(value);
}
if (reference != null) {
bd.getPropertyValues().addPropertyValue(property, reference);
}
}
if (ProtocolConfig.class.equals(beanClass)) {
// 把剩餘的屬性放到protocol的parameters裡面
NamedNodeMap attributes = element.getAttributes();
int len = attributes.getLength();
for (int i = 0; i < len; i++) {
Node node = attributes.item(i);
String name = node.getLocalName();
if (!props.contains(name)) {
if (parameters == null) {
parameters = new ManagedMap();
}
String value = node.getNodeValue();
parameters.put(name, new TypedStringValue(value, String.class));
}
}
bd.getPropertyValues().addPropertyValue("parameters", parameters);

}
return bd;
}
@SuppressWarnings({"unchecked", "rawtypes"})
private static void parseMultiRef(String property, String value, RootBeanDefinition beanDefinition, ParserContext parserContext) {
String[] values = value.split("\\s*[,]+\\s*");
ManagedList list = null;
for (int i = 0; i < values.length; i++) {
String v = values[i];
if (v != null && v.length() > 0) {
if (list == null) {
list = new ManagedList();
}
list.add(new RuntimeBeanReference(v));
}
}
beanDefinition.getPropertyValues().addPropertyValue(property, list);
}
private static void parseProperties(NodeList nodeList, RootBeanDefinition beanDefinition) {
if (nodeList != null && nodeList.getLength() > 0) {
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
if (node instanceof Element) {
if ("property".equals(node.getNodeName()) || "property".equals(node.getLocalName())) {
String name = ((Element) node).getAttribute("name");
if (name != null && name.length() > 0) {
String value = ((Element) node).getAttribute("value");
String ref = ((Element) node).getAttribute("ref");
if (value != null && value.length() > 0) {
beanDefinition.getPropertyValues().addPropertyValue(name, value);
} else if (ref != null && ref.length() > 0) {
beanDefinition.getPropertyValues().addPropertyValue(name, new RuntimeBeanReference(ref));
} else {
throw new UnsupportedOperationException("Unsupported <property> + ""> sub tag, Only supported <property> or <property> + name + "" value="..." />");
}
}
}
}
}
}
}
@SuppressWarnings({"unchecked", "rawtypes"})
private static void parseMethods(String id, NodeList nodeList, RootBeanDefinition beanDefinition, ParserContext parserContext)
throws ClassNotFoundException {
if (nodeList != null && nodeList.getLength() > 0) {
ManagedList methods = null;
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
if (node instanceof Element) {
Element element = (Element) node;

if ("method".equals(node.getNodeName()) || "method".equals(node.getLocalName())) {
String methodName = element.getAttribute("name");
if (methodName == null || methodName.length() == 0) {
throw new IllegalStateException("<method> name attribute == null");
}
if (methods == null) {
methods = new ManagedList();
}
BeanDefinition methodBeanDefinition = parse((Element) node, parserContext, MethodConfig.class, false);
String name = id + "." + methodName;
BeanDefinitionHolder methodBeanDefinitionHolder = new BeanDefinitionHolder(methodBeanDefinition, name);
methods.add(methodBeanDefinitionHolder);
}
}
}
if (methods != null) {
beanDefinition.getPropertyValues().addPropertyValue("methods", methods);
}
}
}
}
/<method>/<property>/<property>/<bean>/<string>/<string>

4.在第一章節中,有一個export的動作在各項配置加載完成後,需要被調用,motan是通過下面的ServiceConfigBean類來實現的:

public class ServiceConfigBean extends ServiceConfig
implements
BeanPostProcessor,
BeanFactoryAware,
InitializingBean,
DisposableBean,
ApplicationListener<contextrefreshedevent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
if (!getExported().get()) {
export();//當配置信息加載完後,調用export方法
}
}

}
/<contextrefreshedevent>

總結一下本章的知識點:

1.使用常規的spring擴展自定義標籤的方式來實現motan對於spring的支持;

2.集成NamespaceHandlerSupport來實現標籤解析類的註冊;

3.實現BeanDefinitionParser的接口來解析具體的標籤;

4.在配置信息加載完後,利用onApplicationEvent事件來調用export方法來發布服務。


分享到:


相關文章: