前面介绍了ServiceBean不是一个简单的Java pojo对象,只拥有get,set方法,它需要在初始化之后执行服务发布的操作。spirng的InitializingBean接口为bean提供了定义初始化方法的方式,它只包括一个afterPropertiesSet()方法,凡是实现了该接口的类,在初始化bean的时候会执行该方法,ServiceBean对象就是通过实现InitializingBean接口实现服务发布的。
ServiceBean代码如下:
package com.lipenglong.ldubbo.config.spring;
import com.lipenglong.ldubbo.config.ServiceConfig;
import org.springframework.beans.factory.InitializingBean;
/**
* ldubbo service对象类,是暴露服务的入口
* <p/>
* Created by lipenglong on 2017/7/21.
*/
public class ServiceBean extends ServiceConfig implements InitializingBean {
private static final long serialVersionUID = 3083255015367616542L;
@Override
public String toString() {
return super.toString();
}
@Override
public void afterPropertiesSet() throws Exception {
export();
}
}
export(),就是服务发布的方法,在父类ServiceConfig中添加该方法的实现,ServiceConfig代码:
package com.lipenglong.ldubbo.config;
import com.lipenglong.ldubbo.rpc.Protocol;
import com.lipenglong.ldubbo.rpc.ProtocolFactory;
/**
* service配置类
* <p/>
* Created by lipenglong on 2017/7/24.
*/
public class ServiceConfig<T> extends AbstractConfig {
private static final long serialVersionUID = 831848002887083456L;
private String interfaceName;
private T ref;
private ProtocolConfig protocolConfig;
private Class<?> interfaceClass;
private Protocol protocol;
public String getInterface() {
return interfaceName;
}
public void setInterface(String interfaceName) {
this.interfaceName = interfaceName;
}
public T getRef() {
return ref;
}
public void setRef(T ref) {
this.ref = ref;
}
public ProtocolConfig getProtocolConfig() {
return protocolConfig;
}
public void setProtocolConfig(ProtocolConfig protocolConfig) {
this.protocolConfig = protocolConfig;
}
public synchronized void export() {
try {
interfaceClass = Class.forName(interfaceName, true, Thread.currentThread().getContextClassLoader());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
protocol = ProtocolFactory.getProtocol(protocolConfig.getName());
protocol.export(interfaceClass, ref);
}
@Override
public String toString() {
return "ServiceConfig{" +
"interfaceName='" + interfaceName + '\'' +
", ref=" + ref +
", protocolConfig=" + protocolConfig +
", interfaceClass=" + interfaceClass +
", protocol=" + protocol +
'}';
}
}
通过ServiceConfig类的setInterface方法,把xml文件中配置的interface属性值赋值给interfaceName,通过setRef方法,把引用的对象赋值给ref属性,这里定义一个泛型T,因为不知道暴露服务的接口具体的实现类的类型。protocolConfig的get,set方法把xml中配置的ProtocolConfig对象引用过来,因为发布服务时需要知道用哪个协议。在上一篇LdubboBeanDefinitionParser类的实现中,有一个判断set方法名称是“protocolConfig”的处理,就是做这个用的。
然后是export()方法的实现,也是比较简单:通过interfaceName得到interfaceClass;根据protocolConfig.getName()获取xml中配置的具体协议(rmi或ldubbo),然后通过ProtocolFactory.getProtocol()方法根据配置的name得到具体的protocol实现类;调用protocol的export方法,实现某个协议具体的服务发布。
Protocol是协议的接口类,定义了两个方法,export方法和refer方法,定义了服务的发布和引用接口,Protocol接口类:
package com.lipenglong.ldubbo.rpc;
import com.lipenglong.ldubbo.config.RegistryConfig;
/**
* rpc协议接口类
* <p/>
* Created by lipenglong on 2017/7/25.
*/
public interface Protocol {
/**
* 暴露远程服务
*
* @param interfaceClass 服务接口class
* @param ref 服务接口的实现
*/
void export(Class<?> interfaceClass, Object ref);
/**
* 引用远程服务
*
* @param interfaceClass 服务接口class
* @param registryConfig registry配置
* @return 服务接口的代理类
*/
<T> T refer(Class<?> interfaceClass, RegistryConfig registryConfig);
}
在介绍具体的协议实现之前,下一篇要先写一下ProtocolFactory.getProtocol()的具体实现,如何根据name得到具体的协议对象类,这里也是参考dubbo框架中应用很广泛的SPI思想。