public class Application {
private String id;
private String name;
private String version;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
@Override
public String toString() {
return "Application [id=" + id + ", name=" + name + ", version=" + version + "]";
}
}
/**
* All rights Reserved, Designed By www.tydic.com
* @Title: ApplicationBeanDefinitionParser.java
* @Package ApplicationBeanDefinitionParser
* @Description: TODO(用一句话描述该文件做什么)
* @author: andyzhu
* @date: 2018年10月8日 上午11:14:30
* @version V1.0
* @Copyright: 2018 www.acc.com Inc. All rights reserved.
* 注意:禁止外泄以及用于其他的商业目
*/
package cn.andy.testdubbo;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
/**
* @author sks
*
*/
public class ApplicationBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
private final Class> beanClass;
private final boolean required;
public ApplicationBeanDefinitionParser(Class> beanClass, boolean required) {
this.beanClass = beanClass;
this.required = required;
}
protected Class getBeanClass(Element element) {
return Application.class;
}
protected void doParse(Element element, BeanDefinitionBuilder bean) {
String id = element.getAttribute("id");
String name = element.getAttribute("name");
String version = element.getAttribute("version");
if (StringUtils.hasText(id)) {
bean.addPropertyValue("id", id);
}
if (StringUtils.hasText(name)) {
bean.addPropertyValue("name", name);
}
if (StringUtils.hasText(version)) {
bean.addPropertyValue("version", version);
}
}
}
/**
* All rights Reserved, Designed By www.tydic.com
* @Title: TtdubboNamespaceHandler.java
* @Package cn.andy.testdubbo
* @Description: TODO(用一句话描述该文件做什么)
* @author: andyzhu
* @date: 2018年10月8日 下午1:58:31
* @version V1.0
* @Copyright: 2018 www.acc.com Inc. All rights reserved.
* 注意:禁止外泄以及用于其他的商业目
*/
package cn.andy.testdubbo;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
/**
* @author sks
*
*/
public class TtdubboNamespaceHandler extends NamespaceHandlerSupport {
/* (non-Javadoc)
* @see org.springframework.beans.factory.xml.NamespaceHandler#init()
*/
@Override
public void init() {
// TODO Auto-generated method stub
registerBeanDefinitionParser("application", new ApplicationBeanDefinitionParser(Application.class, true));
}
}
spring.handlers文件内容,http后面的\是转义字符,注意中间的等号
http\://ttdubbo.oschina.net/schema/ttdubbo=cn.andy.testdubbo.TtdubboNamespaceHandler
spring.schemas文件内容:
http\://ttdubbo.oschina.net/schema/ttdubbo.xsd=META-INF/ttdubbo.xsd
在spring的xml文件中定义:
然后,在测试文件中
public class Test {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-service.xml");
Application application1 = (Application) context.getBean("app1");
System.out.println(application1.toString());
System.out.println("Hello World!");
}
}
例子下载地址https://download.csdn.net/download/andyzhu_2005/10814375
通过上面的流程,来看看dubbo的标签解析是否是这样子的:
其中,DubboNamespaceHandler的内容是:
/*
* Copyright 1999-2011 Alibaba Group.
*
* 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.dubbo.config.spring.schema;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
import com.alibaba.dubbo.common.Version;
import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ConsumerConfig;
import com.alibaba.dubbo.config.ModuleConfig;
import com.alibaba.dubbo.config.MonitorConfig;
import com.alibaba.dubbo.config.ProtocolConfig;
import com.alibaba.dubbo.config.ProviderConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.spring.AnnotationBean;
import com.alibaba.dubbo.config.spring.ReferenceBean;
import com.alibaba.dubbo.config.spring.ServiceBean;
/**
* DubboNamespaceHandler
*
* @author william.liangf
* @export
*/
public class DubboNamespaceHandler extends NamespaceHandlerSupport {
static {
Version.checkDuplicate(DubboNamespaceHandler.class);
}
public void init() {
registerBeanDefinitionParser("application", new DubboBeanDefinitionParser(ApplicationConfig.class, true));
registerBeanDefinitionParser("module", new DubboBeanDefinitionParser(ModuleConfig.class, true));
registerBeanDefinitionParser("registry", new DubboBeanDefinitionParser(RegistryConfig.class, true));
registerBeanDefinitionParser("monitor", new DubboBeanDefinitionParser(MonitorConfig.class, true));
registerBeanDefinitionParser("provider", new DubboBeanDefinitionParser(ProviderConfig.class, true));
registerBeanDefinitionParser("consumer", new DubboBeanDefinitionParser(ConsumerConfig.class, true));
registerBeanDefinitionParser("protocol", new DubboBeanDefinitionParser(ProtocolConfig.class, true));
registerBeanDefinitionParser("service", new DubboBeanDefinitionParser(ServiceBean.class, true));
registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, false));
registerBeanDefinitionParser("annotation", new DubboBeanDefinitionParser(AnnotationBean.class, true));
}
}
这里,对dubbo自定的标签分别进行了解析。其中,service标签就生成了ServiceBean类,而reference就生成了ReferenceBean类。
public class ReferenceBean extends ReferenceConfig implements FactoryBean, ApplicationContextAware, InitializingBean, DisposableBean
ReferenceBean是实现了FactoryBean接口的类,我们知道,Spring中有两种类型的Bean,一种是普通Bean,另一种是工厂Bean,即FactoryBean,这两种Bean都被容器管理,但工厂Bean跟普通Bean不同,其返回的对象不是指定类的一个实例,其返回的是该FactoryBean的getObject方法所返回的对象。
所以,查看ReferenceBean的getObject()方法,
public Object getObject() throws Exception {
return get();
}
public synchronized T get() {
if (destroyed){
throw new IllegalStateException("Already destroyed!");
}
if (ref == null) {
init();
}
return ref;
}
这里的 return get();就是我们的消费端初始化的开始。
public class ServiceBean extends ServiceConfig implements InitializingBean, DisposableBean, ApplicationContextAware, ApplicationListener, BeanNameAware{}
ServiceBean实现了ApplicationListener接口,其在初始化完成后,会回调onApplicationEvent方法:
public void onApplicationEvent(ApplicationEvent event) {
if (ContextRefreshedEvent.class.getName().equals(event.getClass().getName())) {
if (isDelay() && ! isExported() && ! isUnexported()) {
if (logger.isInfoEnabled()) {
logger.info("The service ready on spring started. service: " + getInterface());
}
export();
}
}
}
这个方法就是服务端发布服务的开始。
https://blog.csdn.net/agony_sun/article/details/76853087