2019独角兽企业重金招聘Python工程师标准>>>
简介
dubbo框架spring Schema扩展机制与Spring集成,在spring初始化时候加载dubbo的配置类。 dubbo服务导出的入口类是ServiceBean
的onApplicationEvent
方法 ServiceBean的继承关系如下
public class ServiceBean extends ServiceConfig implements InitializingBean, DisposableBean, ApplicationContextAware, ApplicationListener, BeanNameAware {
private static final long serialVersionUID = 213195494150089726L;
private static transient ApplicationContext SPRING_CONTEXT;
private final transient Service service;
private transient ApplicationContext applicationContext;
private transient String beanName;
private transient boolean supportedApplicationListener;
public ServiceBean() {
this.service = null;
}
public ServiceBean(Service service) {
super(service);
this.service = service;
}
public static ApplicationContext getSpringContext() {
return SPRING_CONTEXT;
}
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
SpringExtensionFactory.addApplicationContext(applicationContext);
if (applicationContext != null) {
SPRING_CONTEXT = applicationContext;
try {
Method method = applicationContext.getClass().getMethod("addApplicationListener", ApplicationListener.class);
method.invoke(applicationContext, this);
this.supportedApplicationListener = true;
} catch (Throwable var5) {
if (applicationContext instanceof AbstractApplicationContext) {
try {
Method method = AbstractApplicationContext.class.getDeclaredMethod("addListener", ApplicationListener.class);
if (!method.isAccessible()) {
method.setAccessible(true);
}
method.invoke(applicationContext, this);
this.supportedApplicationListener = true;
} catch (Throwable var4) {
;
}
}
}
}
}
public void setBeanName(String name) {
this.beanName = name;
}
public Service getService() {
return this.service;
}
public void onApplicationEvent(ContextRefreshedEvent event) {
//如果不延迟导出且exported和unexported都为false 执行导出
if (this.isDelay() && !this.isExported() && !this.isUnexported()) {
if (logger.isInfoEnabled()) {
logger.info("The service ready on spring started. service: " + this.getInterface());
}
this.export();
}
}
private boolean isDelay() {
//调用父类`AbstractServiceConfig`中方法
Integer delay = this.getDelay();
ProviderConfig provider = this.getProvider();
if (delay == null && provider != null) {
//调用父类`AbstractServiceConfig`中getDelay方法
delay = provider.getDelay();
}
//delay == -1表示不需要延迟导出
return this.supportedApplicationListener && (delay == null || delay == -1);
}
}
public ProviderConfig getProvider() {
return this.provider;
}
supportedApplicationListener 变量含义,该变量用于表示当前的 Spring 容器是否支持 ApplicationListener,这个值初始为 false。在 Spring 容器将自己设置到 ServiceBean 中时,ServiceBean 的 setApplicationContext 方法会检测 Spring 容器是否支持 ApplicationListener。若支持,则将 supportedApplicationListener 置为 true。
this.export()调用ServiceConfig中方法
public synchronized void export() {
//如果provider存在,从provider中取export和delay属性
if (this.provider != null) {
if (this.export == null) {
this.export = this.provider.getExport();
}
if (this.delay == null) {
this.delay = this.provider.getDelay();
}
}
//如果未导出 判断delay决定立即导出 还是延迟导出
if (this.export == null || this.export) {
if (this.delay != null && this.delay > 0) {
delayExportExecutor.schedule(new Runnable() {
public void run() {
ServiceConfig.this.doExport();
}
}, (long)this.delay, TimeUnit.MILLISECONDS);
} else {
this.doExport();
}
}
}
doExport
protected synchronized void doExport() {
if (this.unexported) {
throw new IllegalStateException("Already unexported!");
} else if (!this.exported) {
this.exported = true;
if (this.interfaceName != null && this.interfaceName.length() != 0) {
this.checkDefault();
if (this.provider != null) {
if (this.application == null) {
this.application = this.provider.getApplication();
}
if (this.module == null) {
this.module = this.provider.getModule();
}
if (this.registries == null) {
this.registries = this.provider.getRegistries();
}
if (this.monitor == null) {
this.monitor = this.provider.getMonitor();
}
if (this.protocols == null) {
this.protocols = this.provider.getProtocols();
}
}
if (this.module != null) {
if (this.registries == null) {
this.registries = this.module.getRegistries();
}
if (this.monitor == null) {
this.monitor = this.module.getMonitor();
}
}
if (this.application != null) {
if (this.registries == null) {
this.registries = this.application.getRegistries();
}
if (this.monitor == null) {
this.monitor = this.application.getMonitor();
}
}
// 检测 ref 是否为泛化服务类型
if (this.ref instanceof GenericService) {
this.interfaceClass = GenericService.class;
if (StringUtils.isEmpty(this.generic)) {
// 设置 generic = "true"
this.generic = Boolean.TRUE.toString();
}
} else {
try {
this.interfaceClass = Class.forName(this.interfaceName, true, Thread.currentThread().getContextClassLoader());
} catch (ClassNotFoundException var5) {
throw new IllegalStateException(var5.getMessage(), var5);
}
//检查接口中是否有MethodConfig中定义的方法名称,没有抛异常
this.checkInterfaceAndMethods(this.interfaceClass, this.methods);
//检查ref类型是否合法
this.checkRef();
// 设置 generic = "true"
this.generic = Boolean.FALSE.toString();
}
//如果loal = true 或stub = true 加载并检查本地实现是否合法
Class stubClass;
if (this.local != null) {
if ("true".equals(this.local)) {
this.local = this.interfaceName + "Local";
}
try {
stubClass = ClassHelper.forNameWithThreadContextClassLoader(this.local);
} catch (ClassNotFoundException var4) {
throw new IllegalStateException(var4.getMessage(), var4);
}
if (!this.interfaceClass.isAssignableFrom(stubClass)) {
throw new IllegalStateException("The local implementation class " + stubClass.getName() + " not implement interface " + this.interfaceName);
}
}
if (this.stub != null) {
if ("true".equals(this.stub)) {
this.stub = this.interfaceName + "Stub";
}
try {
stubClass = ClassHelper.forNameWithThreadContextClassLoader(this.stub);
} catch (ClassNotFoundException var3) {
throw new IllegalStateException(var3.getMessage(), var3);
}
if (!this.interfaceClass.isAssignableFrom(stubClass)) {
throw new IllegalStateException("The stub implementation class " + stubClass.getName() + " not implement interface " + this.interfaceName);
}
}
// 检测各种对象是否为空,为空则新建,或者抛出异常
//检查dubbo.application.name 设置系统属性dubbo.service.shutdown.wait和dubbo.service.shutdown.wait.seconds
this.checkApplication();
//检查RegistryConfig并使用set方法反射设置属性(先从系统属性中取)
this.checkRegistry();
//设置ProtocalConfig并使用set方法反射设置属性(先从系统属性中取)
this.checkProtocol();
//设置当前ServiceConfig并使用set方法反射设置属性(先从系统属性中取)
appendProperties(this);
this.checkStubAndMock(this.interfaceClass);
if (this.path == null || this.path.length() == 0) {
this.path = this.interfaceName;
}
this.doExportUrls();
// ProviderModel 表示服务提供者模型,此对象中存储了与服务提供者相关的信息。
// 比如服务的配置信息,服务实例等。每个被导出的服务对应一个 ProviderModel。
// ApplicationModel 持有所有的 ProviderModel。
ProviderModel providerModel = new ProviderModel(this.getUniqueServiceName(), this, this.ref);
ApplicationModel.initProviderModel(this.getUniqueServiceName(), providerModel);
} else {
throw new IllegalStateException(" interface not allow null!");
}
}
}
//检查接口类型是否合法
//遍历MethodConfig中方法,检查接口中是否有MethodConfig中定义的方法名称,没有抛异常
protected void checkInterfaceAndMethods(Class> interfaceClass, List methods) {
if (interfaceClass == null) {
throw new IllegalStateException("interface not allow null!");
} else if (!interfaceClass.isInterface()) {
throw new IllegalStateException("The interface class " + interfaceClass + " is not a interface!");
} else {
if (methods != null && methods.size() > 0) {
Iterator i$ = methods.iterator();
while(i$.hasNext()) {
MethodConfig methodBean = (MethodConfig)i$.next();
String methodName = methodBean.getName();
if (methodName == null || methodName.length() == 0) {
throw new IllegalStateException(" name attribute is required! Please check: ");
}
boolean hasMethod = false;
Method[] arr$ = interfaceClass.getMethods();
int len$ = arr$.length;
for(int i$ = 0; i$ < len$; ++i$) {
Method method = arr$[i$];
if (method.getName().equals(methodName)) {
hasMethod = true;
break;
}
}
if (!hasMethod) {
throw new IllegalStateException("The interface " + interfaceClass.getName() + " not found method " + methodName);
}
}
}
}
}
//检查ref类型是否合法
private void checkRef() {
if (this.ref == null) {
throw new IllegalStateException("ref not allow null!");
} else if (!this.interfaceClass.isInstance(this.ref)) {
throw new IllegalStateException("The class " + this.ref.getClass().getName() + " unimplemented interface " + this.interfaceClass + "!");
}
}
doExportUrls
loadRegistries 加载注册中心链接,然后再遍历 ProtocolConfig 集合导出每个服务。并在导出服务的过程中,将服务注册到注册中心。 loadRegistries 方法主要包含如下的逻辑: 检测是否存在注册中心配置类,不存在则抛出异常 构建参数映射集合,也就是 map 构建注册中心链接列表 遍历链接列表,并根据条件决定是否将其添加到 registryList 中
private void doExportUrls() {
List registryURLs = this.loadRegistries(true);
Iterator i$ = this.protocols.iterator();
while(i$.hasNext()) {
ProtocolConfig protocolConfig = (ProtocolConfig)i$.next();
this.doExportUrlsFor1Protocol(protocolConfig, registryURLs);
}
}
protected List loadRegistries(boolean provider) {
//检查注册中心配置
this.checkRegistry();
List registryList = new ArrayList();
if (this.registries != null && this.registries.size() > 0) {
Iterator i$ = this.registries.iterator();
label75:
while(true) {
RegistryConfig config;
String address;
do {
do {
do {
if (!i$.hasNext()) {
return registryList;
}
config = (RegistryConfig)i$.next();
address = config.getAddress();
// 若 address 为空,则将其设为 0.0.0.0
if (address == null || address.length() == 0) {
address = "0.0.0.0";
}
// 从系统属性中加载注册中心地址
String sysaddress = System.getProperty("dubbo.registry.address");
if (sysaddress != null && sysaddress.length() > 0) {
address = sysaddress;
}
} while(address == null);
} while(address.length() <= 0);
} while("N/A".equalsIgnoreCase(address));
Map map = new HashMap();
// 添加 ApplicationConfig 中的字段信息到 map 中
appendParameters(map, this.application);
// 添加 RegistryConfig 字段信息到 map 中
appendParameters(map, config);
// 添加 path、pid,protocol 等信息到 map 中
map.put("path", RegistryService.class.getName());
map.put("dubbo", Version.getVersion());
map.put("timestamp", String.valueOf(System.currentTimeMillis()));
if (ConfigUtils.getPid() > 0) {
map.put("pid", String.valueOf(ConfigUtils.getPid()));
}
if (!map.containsKey("protocol")) {
if (ExtensionLoader.getExtensionLoader(RegistryFactory.class).hasExtension("remote")) {
map.put("protocol", "remote");
} else {
map.put("protocol", "dubbo");
}
}
// 解析得到 URL 列表,address 可能包含多个注册中心 ip,
// 因此解析得到的是一个 URL 列表
List urls = UrlUtils.parseURLs(address, map);
Iterator i$ = urls.iterator();
while(true) {
URL url;
do {
if (!i$.hasNext()) {
continue label75;
}
url = (URL)i$.next();
url = url.addParameter("registry", url.getProtocol());
// 将 URL 协议头设置为 registry
url = url.setProtocol("registry");
} while((!provider || !url.getParameter("register", true)) && (provider || !url.getParameter("subscribe", true)));
registryList.add(url);
}
}
} else {
return registryList;
}
}
//解析address 如果address以;或|符号分隔 则拆分后解析 返回List
public static List parseURLs(String address, Map defaults) {
if (address != null && address.length() != 0) {
String[] addresses = Constants.REGISTRY_SPLIT_PATTERN.split(address);
if (addresses != null && addresses.length != 0) {
List registries = new ArrayList();
String[] arr$ = addresses;
int len$ = addresses.length;
for(int i$ = 0; i$ < len$; ++i$) {
String addr = arr$[i$];
registries.add(parseURL(addr, defaults));
}
return registries;
} else {
return null;
}
} else {
return null;
}
}
public static URL parseURL(String address, Map defaults) {
if (address != null && address.length() != 0) {
String url;
//1 如果包含:// 直接返回url
//2 否则用,拆分成address数组 后拼接url
// 以172.19.103.55:2181,172.19.103.57:2181,172.19.103.54:2181为例
// 返回172.19.103.55:2181?backup=172.19.103.57:2181,172.19.103.54:2181
if (address.indexOf("://") >= 0) {
url = address;
} else {
String[] addresses = Constants.COMMA_SPLIT_PATTERN.split(address);
url = addresses[0];
if (addresses.length > 1) {
StringBuilder backup = new StringBuilder();
for(int i = 1; i < addresses.length; ++i) {
if (i > 1) {
backup.append(",");
}
backup.append(addresses[i]);
}
url = url + "?backup=" + backup.toString();
}
}
String defaultProtocol = defaults == null ? null : (String)defaults.get("protocol");
if (defaultProtocol == null || defaultProtocol.length() == 0) {
defaultProtocol = "dubbo";
}
String defaultUsername = defaults == null ? null : (String)defaults.get("username");
String defaultPassword = defaults == null ? null : (String)defaults.get("password");
int defaultPort = StringUtils.parseInteger(defaults == null ? null : (String)defaults.get("port"));
String defaultPath = defaults == null ? null : (String)defaults.get("path");
Map defaultParameters = defaults == null ? null : new HashMap(defaults);
if (defaultParameters != null) {
defaultParameters.remove("protocol");
defaultParameters.remove("username");
defaultParameters.remove("password");
defaultParameters.remove("host");
defaultParameters.remove("port");
defaultParameters.remove("path");
}
//构造URL
URL u = URL.valueOf(url);
boolean changed = false;
String protocol = u.getProtocol();
String username = u.getUsername();
String password = u.getPassword();
String host = u.getHost();
int port = u.getPort();
String path = u.getPath();
Map parameters = new HashMap(u.getParameters());
if ((protocol == null || protocol.length() == 0) && defaultProtocol != null && defaultProtocol.length() > 0) {
changed = true;
protocol = defaultProtocol;
}
if ((username == null || username.length() == 0) && defaultUsername != null && defaultUsername.length() > 0) {
changed = true;
username = defaultUsername;
}
if ((password == null || password.length() == 0) && defaultPassword != null && defaultPassword.length() > 0) {
changed = true;
password = defaultPassword;
}
if (port <= 0) {
if (defaultPort > 0) {
changed = true;
port = defaultPort;
} else {
changed = true;
port = 9090;
}
}
if ((path == null || path.length() == 0) && defaultPath != null && defaultPath.length() > 0) {
changed = true;
path = defaultPath;
}
if (defaultParameters != null && defaultParameters.size() > 0) {
Iterator i$ = defaultParameters.entrySet().iterator();
label119:
while(true) {
String key;
String defaultValue;
String value;
do {
do {
do {
if (!i$.hasNext()) {
break label119;
}
Entry entry = (Entry)i$.next();
key = (String)entry.getKey();
defaultValue = (String)entry.getValue();
} while(defaultValue == null);
} while(defaultValue.length() <= 0);
value = (String)parameters.get(key);
} while(value != null && value.length() != 0);
changed = true;
parameters.put(key, defaultValue);
}
}
//如果URL中有username等有一个未指定 则从默认配置读取缺失的配置
if (changed) {
u = new URL(protocol, username, password, host, port, path, parameters);
}
return u;
} else {
return null;
}
}
doExportUrlsFor1Protocol
private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List registryURLs) {
String name = protocolConfig.getName();
//设置dubbo为默认协议
if (name == null || name.length() == 0) {
name = "dubbo";
}
// 添加 side、版本、时间戳以及进程号等信息到 map 中
Map map = new HashMap();
map.put("side", "provider");
map.put("dubbo", Version.getVersion());
map.put("timestamp", String.valueOf(System.currentTimeMillis()));
if (ConfigUtils.getPid() > 0) {
map.put("pid", String.valueOf(ConfigUtils.getPid()));
}
// 通过反射将对象的字段信息添加到 map 中
appendParameters(map, this.application);
appendParameters(map, this.module);
appendParameters(map, this.provider, "default");
appendParameters(map, protocolConfig);
appendParameters(map, this);
//这段代码用于检测 标签中的配置信息,并将相关配置添加到 map 中。
if (this.methods != null && this.methods.size() > 0) {
Iterator i$ = this.methods.iterator();
label188:
while(true) {
MethodConfig method;
List arguments;
do {
do {
if (!i$.hasNext()) {
break label188;
}
method = (MethodConfig)i$.next();
appendParameters(map, method, method.getName());
String retryKey = method.getName() + ".retry";
if (map.containsKey(retryKey)) {
String retryValue = (String)map.remove(retryKey);
if ("false".equals(retryValue)) {
map.put(method.getName() + ".retries", "0");
}
}
arguments = method.getArguments();
} while(arguments == null);
} while(arguments.size() <= 0);
Iterator i$ = arguments.iterator();
while(true) {
ArgumentConfig argument;
Method[] methods;
do {
do {
while(true) {
if (!i$.hasNext()) {
continue label188;
}
argument = (ArgumentConfig)i$.next();
if (argument.getType() != null && argument.getType().length() > 0) {
methods = this.interfaceClass.getMethods();
break;
}
if (argument.getIndex() == -1) {
throw new IllegalArgumentException("argument config must set index or type attribute.eg: or ");
}
appendParameters(map, argument, method.getName() + "." + argument.getIndex());
}
} while(methods == null);
} while(methods.length <= 0);
for(int i = 0; i < methods.length; ++i) {
String methodName = methods[i].getName();
if (methodName.equals(method.getName())) {
Class>[] argtypes = methods[i].getParameterTypes();
if (argument.getIndex() != -1) {
if (!argtypes[argument.getIndex()].getName().equals(argument.getType())) {
throw new IllegalArgumentException("argument config error : the index attribute and type attribute not match :index :" + argument.getIndex() + ", type:" + argument.getType());
}
appendParameters(map, argument, method.getName() + "." + argument.getIndex());
} else {
for(int j = 0; j < argtypes.length; ++j) {
Class> argclazz = argtypes[j];
if (argclazz.getName().equals(argument.getType())) {
appendParameters(map, argument, method.getName() + "." + j);
if (argument.getIndex() != -1 && argument.getIndex() != j) {
throw new IllegalArgumentException("argument config error : the index attribute and type attribute not match :index :" + argument.getIndex() + ", type:" + argument.getType());
}
}
}
}
}
}
}
}
}
String contextPath;
if (ProtocolUtils.isGeneric(this.generic)) {
map.put("generic", this.generic);
map.put("methods", "*");
} else {
contextPath = Version.getVersion(this.interfaceClass, this.version);
if (contextPath != null && contextPath.length() > 0) {
map.put("revision", contextPath);
}
// 为接口生成包裹类 Wrapper,Wrapper 中包含了接口的详细信息,比如接口方法名数组,字段信息等
String[] methods = Wrapper.getWrapper(this.interfaceClass).getMethodNames();
if (methods.length == 0) {
logger.warn("NO method found in service interface " + this.interfaceClass.getName());
map.put("methods", "*");
} else {
// 将逗号作为分隔符连接方法名,并将连接后的字符串放入 map 中
map.put("methods", StringUtils.join(new HashSet(Arrays.asList(methods)), ","));
}
}
// 添加 token 到 map 中
if (!ConfigUtils.isEmpty(this.token)) {
if (ConfigUtils.isDefault(this.token)) {
map.put("token", UUID.randomUUID().toString());
} else {
map.put("token", this.token);
}
}
if ("injvm".equals(protocolConfig.getName())) {
protocolConfig.setRegister(false);
map.put("notify", "false");
}
contextPath = protocolConfig.getContextpath();
if ((contextPath == null || contextPath.length() == 0) && this.provider != null) {
contextPath = this.provider.getContextpath();
}
String host = this.findConfigedHosts(protocolConfig, registryURLs, map);
Integer port = this.findConfigedPorts(protocolConfig, name, map);
//上面的代码首先是将一些信息,比如版本、时间戳、方法名以及各种配置对象的字段信息放入到 map 中,map 中的内容将作为 URL 的查询字符串。 构建好 map 后,紧接着是获取上下文路径、主机名以及端口号等信息。最后将 map 和主机名等数据传给 URL 构造方法创建 URL 对象。
URL url = new URL(name, host, port, (contextPath != null && contextPath.length() != 0 ? contextPath + "/" : "") + this.path, map);
// 加载 ConfiguratorFactory,并生成 Configurator 实例,然后通过实例配置 url
if (ExtensionLoader.getExtensionLoader(ConfiguratorFactory.class).hasExtension(url.getProtocol())) {
url = ((ConfiguratorFactory)ExtensionLoader.getExtensionLoader(ConfiguratorFactory.class).getExtension(url.getProtocol())).getConfigurator(url).configure(url);
}
String scope = url.getParameter("scope");
if (!"none".toString().equalsIgnoreCase(scope)) {
// scope != remote,导出到本地
if (!"remote".toString().equalsIgnoreCase(scope)) {
this.exportLocal(url);
}
// scope != local,导出到远程
if (!"local".toString().equalsIgnoreCase(scope)) {
if (logger.isInfoEnabled()) {
logger.info("Export dubbo service " + this.interfaceClass.getName() + " to url " + url);
}
if (registryURLs != null && registryURLs.size() > 0) {
Iterator i$ = registryURLs.iterator();
while(i$.hasNext()) {
URL registryURL = (URL)i$.next();
url = url.addParameterIfAbsent("dynamic", registryURL.getParameter("dynamic"));
URL monitorUrl = this.loadMonitor(registryURL);
if (monitorUrl != null) {
url = url.addParameterAndEncoded("monitor", monitorUrl.toFullString());
}
if (logger.isInfoEnabled()) {
logger.info("Register dubbo service " + this.interfaceClass.getName() + " url " + url + " to registry " + registryURL);
}
// 为服务提供类(ref)生成 Invoker
Invoker> invoker = proxyFactory.getInvoker(this.ref, this.interfaceClass, registryURL.addParameterAndEncoded("export", url.toFullString()));
DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this);
Exporter> exporter = protocol.export(wrapperInvoker);
this.exporters.add(exporter);
}
} else {
// 不存在注册中心,仅导出服务
Invoker> invoker = proxyFactory.getInvoker(this.ref, this.interfaceClass, url);
DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this);
Exporter> exporter = protocol.export(wrapperInvoker);
this.exporters.add(exporter);
}
}
}
this.urls.add(url);
}
上面代码根据 url 中的 scope 参数决定服务导出方式,分别如下:
scope = none,不导出服务
scope != remote,导出到本地
scope != local,导出到远程
不管是导出到本地,还是远程。进行服务导出之前,均需要先创建 Invoker
Invoker创建
Invoker 是由 ProxyFactory 创建而来,Dubbo 默认的 ProxyFactory 实现类是 JavassistProxyFactory
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.alibaba.dubbo.rpc.proxy.javassist;
import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.common.bytecode.Proxy;
import com.alibaba.dubbo.common.bytecode.Wrapper;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.proxy.AbstractProxyFactory;
import com.alibaba.dubbo.rpc.proxy.AbstractProxyInvoker;
import com.alibaba.dubbo.rpc.proxy.InvokerInvocationHandler;
public class JavassistProxyFactory extends AbstractProxyFactory {
public JavassistProxyFactory() {
}
public T getProxy(Invoker invoker, Class>[] interfaces) {
return Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));
}
public Invoker getInvoker(T proxy, Class type, URL url) {
// 为目标类创建 Wrapper
final Wrapper wrapper = Wrapper.getWrapper(proxy.getClass().getName().indexOf(36) < 0 ? proxy.getClass() : type);
// 创建匿名 Invoker 类对象,并实现 doInvoke 方法。
return new AbstractProxyInvoker(proxy, type, url) {
protected Object doInvoke(T proxy, String methodName, Class>[] parameterTypes, Object[] arguments) throws Throwable {
return wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments);
}
};
}
}
JavassistProxyFactory 创建了一个继承自 AbstractProxyInvoker 类的匿名对象,并覆写了抽象方法 doInvoke。覆写后的 doInvoke 逻辑比较简单,仅是将调用请求转发给了 Wrapper 类的 invokeMethod 方法。Wrapper 用于“包裹”目标类,Wrapper 是一个抽象类,仅可通过 getWrapper(Class) 方法创建子类。在创建 Wrapper 子类的过程中,子类代码生成逻辑会对 getWrapper 方法传入的 Class 对象进行解析,拿到诸如类方法,类成员变量等信息。以及生成 invokeMethod 方法代码和其他一些方法代码。代码生成完毕后,通过 Javassist 生成 Class 对象,最后再通过反射创建 Wrapper 实例
Wrapper
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.alibaba.dubbo.common.bytecode;
import com.alibaba.dubbo.common.utils.ClassHelper;
import com.alibaba.dubbo.common.utils.ReflectUtils;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.regex.Matcher;
public abstract class Wrapper {
private static final Map, Wrapper> WRAPPER_MAP = new ConcurrentHashMap();
private static final String[] EMPTY_STRING_ARRAY = new String[0];
private static final String[] OBJECT_METHODS = new String[]{"getClass", "hashCode", "toString", "equals"};
//Object对象的Wrapper实现
private static final Wrapper OBJECT_WRAPPER = new Wrapper() {
public String[] getMethodNames() {
return Wrapper.OBJECT_METHODS;
}
public String[] getDeclaredMethodNames() {
return Wrapper.OBJECT_METHODS;
}
public String[] getPropertyNames() {
return Wrapper.EMPTY_STRING_ARRAY;
}
public Class> getPropertyType(String pn) {
return null;
}
public Object getPropertyValue(Object instance, String pn) throws NoSuchPropertyException {
throw new NoSuchPropertyException("Property [" + pn + "] not found.");
}
public void setPropertyValue(Object instance, String pn, Object pv) throws NoSuchPropertyException {
throw new NoSuchPropertyException("Property [" + pn + "] not found.");
}
public boolean hasProperty(String name) {
return false;
}
public Object invokeMethod(Object instance, String mn, Class>[] types, Object[] args) throws NoSuchMethodException {
if ("getClass".equals(mn)) {
return instance.getClass();
} else if ("hashCode".equals(mn)) {
return instance.hashCode();
} else if ("toString".equals(mn)) {
return instance.toString();
} else if ("equals".equals(mn)) {
if (args.length == 1) {
return instance.equals(args[0]);
} else {
throw new IllegalArgumentException("Invoke method [" + mn + "] argument number error.");
}
} else {
throw new NoSuchMethodException("Method [" + mn + "] not found.");
}
}
};
private static AtomicLong WRAPPER_CLASS_COUNTER = new AtomicLong(0L);
public Wrapper() {
}
public static Wrapper getWrapper(Class> c) {
while(ClassGenerator.isDynamicClass(c)) {
c = c.getSuperclass();
}
//如果是object类型 返回Object的Wrapper
if (c == Object.class) {
return OBJECT_WRAPPER;
} else {
//从缓存取,没有的话创建Wrapper,并放入缓存
Wrapper ret = (Wrapper)WRAPPER_MAP.get(c);
if (ret == null) {
ret = makeWrapper(c);
WRAPPER_MAP.put(c, ret);
}
return ret;
}
}
private static Wrapper makeWrapper(Class> c) {
//如果是primitive类型 抛异常
if (c.isPrimitive()) {
throw new IllegalArgumentException("Can not create wrapper for primitive type: " + c);
} else {
String name = c.getName();
ClassLoader cl = ClassHelper.getClassLoader(c);
// c1 用于存储 setPropertyValue 方法代码
StringBuilder c1 = new StringBuilder("public void setPropertyValue(Object o, String n, Object v){ ");
// c2 用于存储 getPropertyValue 方法代码
StringBuilder c2 = new StringBuilder("public Object getPropertyValue(Object o, String n){ ");
// c3 用于存储 invokeMethod 方法代码
StringBuilder c3 = new StringBuilder("public Object invokeMethod(Object o, String n, Class[] p, Object[] v) throws " + InvocationTargetException.class.getName() + "{ ");
// 生成类型转换代码及异常捕捉代码,比如:
// DemoService w; try { w = ((DemoServcie) $1); }}catch(Throwable e){ throw new IllegalArgumentException(e); }
c1.append(name).append(" w; try{ w = ((").append(name).append(")$1); }catch(Throwable e){ throw new IllegalArgumentException(e); }");
c2.append(name).append(" w; try{ w = ((").append(name).append(")$1); }catch(Throwable e){ throw new IllegalArgumentException(e); }");
c3.append(name).append(" w; try{ w = ((").append(name).append(")$1); }catch(Throwable e){ throw new IllegalArgumentException(e); }");
// pts 用于存储成员变量名和类型
Map> pts = new HashMap();
// ms 用于存储方法描述信息(可理解为方法签名)及 Method 实例
Map ms = new LinkedHashMap();
// mns 为方法名列表
List mns = new ArrayList();
// dmns 用于存储“定义在当前类中的方法”的名称
List dmns = new ArrayList();
Field[] arr$ = c.getFields();
int len$ = arr$.length;
for(int i$ = 0; i$ < len$; ++i$) {
Field f = arr$[i$];
String fn = f.getName();
Class> ft = f.getType();
// 生成条件判断及赋值语句,比如:
// if( $2.equals("name") ) { w.name = (java.lang.String) $3; return;}
// if( $2.equals("age") ) { w.age = ((Number) $3).intValue(); return;}
if (!Modifier.isStatic(f.getModifiers()) && !Modifier.isTransient(f.getModifiers())) {
c1.append(" if( $2.equals(\"").append(fn).append("\") ){ w.").append(fn).append("=").append(arg(ft, "$3")).append("; return; }");
// 生成条件判断及返回语句,比如:
// if( $2.equals("name") ) { return ($w)w.name; }
c2.append(" if( $2.equals(\"").append(fn).append("\") ){ return ($w)w.").append(fn).append("; }");
pts.put(fn, ft);
}
}
Method[] methods = c.getMethods();
// 检测 c 中是否包含在当前类中声明的方法
boolean hasMethod = hasMethods(methods);
if (hasMethod) {
c3.append(" try{");
}
Method[] arr$ = methods;
int len$ = methods.length;
int ix;
for(int i$ = 0; i$ < len$; ++i$) {
Method m = arr$[i$];
if (m.getDeclaringClass() != Object.class) {
String mn = m.getName();
c3.append(" if( \"").append(mn).append("\".equals( $2 ) ");
ix = m.getParameterTypes().length;
// 生成“运行时传入的参数数量与方法参数列表长度”判断语句,比如:
// && $3.length == 2
c3.append(" && ").append(" $3.length == ").append(ix);
boolean override = false;
Method[] arr$ = methods;
int len$ = methods.length;
for(int i$ = 0; i$ < len$; ++i$) {
Method m2 = arr$[i$];
// 检测方法是否存在重载情况,条件为:方法对象不同 && 方法名相同
if (m != m2 && m.getName().equals(m2.getName())) {
override = true;
break;
}
}
if (override && ix > 0) {
for(int l = 0; l < ix; ++l) {
c3.append(" && ").append(" $3[").append(l).append("].getName().equals(\"").append(m.getParameterTypes()[l].getName()).append("\")");
}
}
c3.append(" ) { ");
if (m.getReturnType() == Void.TYPE) {
c3.append(" w.").append(mn).append('(').append(args(m.getParameterTypes(), "$4")).append(");").append(" return null;");
} else {
c3.append(" return ($w)w.").append(mn).append('(').append(args(m.getParameterTypes(), "$4")).append(");");
}
c3.append(" }");
mns.add(mn);
if (m.getDeclaringClass() == c) {
dmns.add(mn);
}
ms.put(ReflectUtils.getDesc(m), m);
}
}
if (hasMethod) {
c3.append(" } catch(Throwable e) { ");
c3.append(" throw new java.lang.reflect.InvocationTargetException(e); ");
c3.append(" }");
}
c3.append(" throw new " + NoSuchMethodException.class.getName() + "(\"Not found method \\\"\"+$2+\"\\\" in class " + c.getName() + ".\"); }");
Iterator i$ = ms.entrySet().iterator();
while(i$.hasNext()) {
Entry entry = (Entry)i$.next();
String md = (String)entry.getKey();
Method method = (Method)entry.getValue();
Matcher matcher;
String pn;
if ((matcher = ReflectUtils.GETTER_METHOD_DESC_PATTERN.matcher(md)).matches()) {
pn = propertyName(matcher.group(1));
c2.append(" if( $2.equals(\"").append(pn).append("\") ){ return ($w)w.").append(method.getName()).append("(); }");
pts.put(pn, method.getReturnType());
} else if ((matcher = ReflectUtils.IS_HAS_CAN_METHOD_DESC_PATTERN.matcher(md)).matches()) {
pn = propertyName(matcher.group(1));
c2.append(" if( $2.equals(\"").append(pn).append("\") ){ return ($w)w.").append(method.getName()).append("(); }");
pts.put(pn, method.getReturnType());
} else if ((matcher = ReflectUtils.SETTER_METHOD_DESC_PATTERN.matcher(md)).matches()) {
Class> pt = method.getParameterTypes()[0];
String pn = propertyName(matcher.group(1));
c1.append(" if( $2.equals(\"").append(pn).append("\") ){ w.").append(method.getName()).append("(").append(arg(pt, "$3")).append("); return; }");
pts.put(pn, pt);
}
}
c1.append(" throw new " + NoSuchPropertyException.class.getName() + "(\"Not found property \\\"\"+$2+\"\\\" filed or setter method in class " + c.getName() + ".\"); }");
c2.append(" throw new " + NoSuchPropertyException.class.getName() + "(\"Not found property \\\"\"+$2+\"\\\" filed or setter method in class " + c.getName() + ".\"); }");
long id = WRAPPER_CLASS_COUNTER.getAndIncrement();
ClassGenerator cc = ClassGenerator.newInstance(cl);
cc.setClassName((Modifier.isPublic(c.getModifiers()) ? Wrapper.class.getName() : c.getName() + "$sw") + id);
cc.setSuperClass(Wrapper.class);
cc.addDefaultConstructor();
cc.addField("public static String[] pns;");
cc.addField("public static " + Map.class.getName() + " pts;");
cc.addField("public static String[] mns;");
cc.addField("public static String[] dmns;");
int i = 0;
for(ix = ms.size(); i < ix; ++i) {
cc.addField("public static Class[] mts" + i + ";");
}
cc.addMethod("public String[] getPropertyNames(){ return pns; }");
cc.addMethod("public boolean hasProperty(String n){ return pts.containsKey($1); }");
cc.addMethod("public Class getPropertyType(String n){ return (Class)pts.get($1); }");
cc.addMethod("public String[] getMethodNames(){ return mns; }");
cc.addMethod("public String[] getDeclaredMethodNames(){ return dmns; }");
cc.addMethod(c1.toString());
cc.addMethod(c2.toString());
cc.addMethod(c3.toString());
try {
Class> wc = cc.toClass();
wc.getField("pts").set((Object)null, pts);
wc.getField("pns").set((Object)null, pts.keySet().toArray(new String[0]));
wc.getField("mns").set((Object)null, mns.toArray(new String[0]));
wc.getField("dmns").set((Object)null, dmns.toArray(new String[0]));
ix = 0;
Iterator i$ = ms.values().iterator();
while(i$.hasNext()) {
Method m = (Method)i$.next();
wc.getField("mts" + ix++).set((Object)null, m.getParameterTypes());
}
Wrapper var50 = (Wrapper)wc.newInstance();
return var50;
} catch (RuntimeException var27) {
throw var27;
} catch (Throwable var28) {
throw new RuntimeException(var28.getMessage(), var28);
} finally {
cc.release();
ms.clear();
mns.clear();
dmns.clear();
}
}
}
private static String arg(Class> cl, String name) {
if (cl.isPrimitive()) {
if (cl == Boolean.TYPE) {
return "((Boolean)" + name + ").booleanValue()";
} else if (cl == Byte.TYPE) {
return "((Byte)" + name + ").byteValue()";
} else if (cl == Character.TYPE) {
return "((Character)" + name + ").charValue()";
} else if (cl == Double.TYPE) {
return "((Number)" + name + ").doubleValue()";
} else if (cl == Float.TYPE) {
return "((Number)" + name + ").floatValue()";
} else if (cl == Integer.TYPE) {
return "((Number)" + name + ").intValue()";
} else if (cl == Long.TYPE) {
return "((Number)" + name + ").longValue()";
} else if (cl == Short.TYPE) {
return "((Number)" + name + ").shortValue()";
} else {
throw new RuntimeException("Unknown primitive type: " + cl.getName());
}
} else {
return "(" + ReflectUtils.getName(cl) + ")" + name;
}
}
private static String args(Class>[] cs, String name) {
int len = cs.length;
if (len == 0) {
return "";
} else {
StringBuilder sb = new StringBuilder();
for(int i = 0; i < len; ++i) {
if (i > 0) {
sb.append(',');
}
sb.append(arg(cs[i], name + "[" + i + "]"));
}
return sb.toString();
}
}
private static String propertyName(String pn) {
return pn.length() != 1 && !Character.isLowerCase(pn.charAt(1)) ? pn : Character.toLowerCase(pn.charAt(0)) + pn.substring(1);
}
private static boolean hasMethods(Method[] methods) {
if (methods != null && methods.length != 0) {
Method[] arr$ = methods;
int len$ = methods.length;
for(int i$ = 0; i$ < len$; ++i$) {
Method m = arr$[i$];
if (m.getDeclaringClass() != Object.class) {
return true;
}
}
return false;
} else {
return false;
}
}
public abstract String[] getPropertyNames();
public abstract Class> getPropertyType(String var1);
public abstract boolean hasProperty(String var1);
public abstract Object getPropertyValue(Object var1, String var2) throws NoSuchPropertyException, IllegalArgumentException;
public abstract void setPropertyValue(Object var1, String var2, Object var3) throws NoSuchPropertyException, IllegalArgumentException;
public Object[] getPropertyValues(Object instance, String[] pns) throws NoSuchPropertyException, IllegalArgumentException {
Object[] ret = new Object[pns.length];
for(int i = 0; i < ret.length; ++i) {
ret[i] = this.getPropertyValue(instance, pns[i]);
}
return ret;
}
public void setPropertyValues(Object instance, String[] pns, Object[] pvs) throws NoSuchPropertyException, IllegalArgumentException {
if (pns.length != pvs.length) {
throw new IllegalArgumentException("pns.length != pvs.length");
} else {
for(int i = 0; i < pns.length; ++i) {
this.setPropertyValue(instance, pns[i], pvs[i]);
}
}
}
public abstract String[] getMethodNames();
public abstract String[] getDeclaredMethodNames();
public boolean hasMethod(String name) {
String[] arr$ = this.getMethodNames();
int len$ = arr$.length;
for(int i$ = 0; i$ < len$; ++i$) {
String mn = arr$[i$];
if (mn.equals(name)) {
return true;
}
}
return false;
}
public abstract Object invokeMethod(Object var1, String var2, Class>[] var3, Object[] var4) throws NoSuchMethodException, InvocationTargetException;
}
通过 ClassGenerator 为刚刚生成的代码构建 Class 类,并通过反射创建对象。ClassGenerator 是 Dubbo 自己封装的,该类的核心是 toClass() 的重载方法 toClass(ClassLoader, ProtectionDomain),该方法通过 javassist 构建 Class
服务远程导出
- 调用 doLocalExport 导出服务
- 向注册中心注册服务
- 向注册中心进行订阅 override 数据
- 创建并返回 DestroyableExporter
public Exporter export(Invoker originInvoker) throws RpcException {
// 导出服务
RegistryProtocol.ExporterChangeableWrapper exporter = this.doLocalExport(originInvoker);
// 获取注册中心 URL,以 zookeeper 注册中心为例,得到的示例 URL 如下:
// zookeeper://127.0.0.1:2181/com.alibaba.dubbo.registry.RegistryService?application=demo-provider&dubbo=2.0.2&export=dubbo%3A%2F%2F172.17.48.52%3A20880%2Fcom.alibaba.dubbo.demo.DemoService%3Fanyhost%3Dtrue%26application%3Ddemo-provider
URL registryUrl = this.getRegistryUrl(originInvoker);
Registry registry = this.getRegistry(originInvoker);
URL registedProviderUrl = this.getRegistedProviderUrl(originInvoker);
boolean register = registedProviderUrl.getParameter("register", true);
ProviderConsumerRegTable.registerProvider(originInvoker, registryUrl, registedProviderUrl);
if (register) {
this.register(registryUrl, registedProviderUrl);
ProviderConsumerRegTable.getProviderWrapper(originInvoker).setReg(true);
}
URL overrideSubscribeUrl = this.getSubscribedOverrideUrl(registedProviderUrl);
RegistryProtocol.OverrideListener overrideSubscribeListener = new RegistryProtocol.OverrideListener(overrideSubscribeUrl, originInvoker);
this.overrideListeners.put(overrideSubscribeUrl, overrideSubscribeListener);
registry.subscribe(overrideSubscribeUrl, overrideSubscribeListener);
return new RegistryProtocol.DestroyableExporter(exporter, originInvoker, overrideSubscribeUrl, registedProviderUrl);
}
如果是dubbo协议,调用DubboProtocal的export()
public Exporter export(Invoker invoker) throws RpcException {
URL url = invoker.getUrl();
String key = serviceKey(url);
// 创建 DubboExporter
DubboExporter exporter = new DubboExporter(invoker, key, this.exporterMap);
this.exporterMap.put(key, exporter);
Boolean isStubSupportEvent = url.getParameter("dubbo.stub.event", false);
Boolean isCallbackservice = url.getParameter("is_callback_service", false);
if (isStubSupportEvent && !isCallbackservice) {
String stubServiceMethods = url.getParameter("dubbo.stub.event.methods");
if (stubServiceMethods != null && stubServiceMethods.length() != 0) {
this.stubServiceMethodsMap.put(url.getServiceKey(), stubServiceMethods);
} else if (this.logger.isWarnEnabled()) {
this.logger.warn(new IllegalStateException("consumer [" + url.getParameter("interface") + "], has set stubproxy support event ,but no stub methods founded."));
}
}
// 启动服务器
this.openServer(url);
return exporter;
}
private void openServer(URL url) {
// 获取 host:port,并将其作为服务器实例的 key,用于标识当前的服务器实例
String key = url.getAddress();
boolean isServer = url.getParameter("isserver", true);
if (isServer) {
ExchangeServer server = (ExchangeServer)this.serverMap.get(key);
if (server == null) {
// 创建服务器实例
this.serverMap.put(key, this.createServer(url));
} else {
// 服务器已创建,则根据 url 中的配置重置服务器
server.reset(url);
}
}
}
server = Exchangers.bind(url, this.requestHandler);
} catch (RemotingException var5) {
throw new RpcException("Fail to start server(url: " + url + ") " + var5.getMessage(), var5);
}
str = url.getParameter("client");
if (str != null && str.length() > 0) {
Set supportedTypes = ExtensionLoader.getExtensionLoader(Transporter.class).getSupportedExtensions();
if (!supportedTypes.contains(str)) {
throw new RpcException("Unsupported client type: " + str);
}
}
return server;
}
}
调用Exchanger
的实现类HeaderExchanger
public class HeaderExchanger implements Exchanger {
public static final String NAME = "header";
public HeaderExchanger() {
}
public ExchangeClient connect(URL url, ExchangeHandler handler) throws RemotingException {
return new HeaderExchangeClient(Transporters.connect(url, new ChannelHandler[]{new DecodeHandler(new HeaderExchangeHandler(handler))}), true);
}
public ExchangeServer bind(URL url, ExchangeHandler handler) throws RemotingException {
return new HeaderExchangeServer(Transporters.bind(url, new ChannelHandler[]{new DecodeHandler(new HeaderExchangeHandler(handler))}));
}
}
Transporters.bind()如下
public static Server bind(URL url, ChannelHandler... handlers) throws RemotingException {
if (url == null) {
throw new IllegalArgumentException("url == null");
} else if (handlers != null && handlers.length != 0) {
Object handler;
if (handlers.length == 1) {
handler = handlers[0];
} else {
handler = new ChannelHandlerDispatcher(handlers);
}
return getTransporter().bind(url, (ChannelHandler)handler);
} else {
throw new IllegalArgumentException("handlers == null");
}
}
//获取自适应的Transporter扩展 默认NettyTransporter
public static Transporter getTransporter() {
return (Transporter)ExtensionLoader.getExtensionLoader(Transporter.class).getAdaptiveExtension();
}
public class NettyTransporter implements Transporter {
public static final String NAME = "netty";
public NettyTransporter() {
}
public Server bind(URL url, ChannelHandler listener) throws RemotingException {
return new NettyServer(url, listener);
}
public Client connect(URL url, ChannelHandler listener) throws RemotingException {
return new NettyClient(url, listener);
}
}
NettyServer继承AbstractServer,在AbstractServer定义了模板方法doOpen()和doClose(),NettyServer的实现如下
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.alibaba.dubbo.remoting.transport.netty;
import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.common.logger.Logger;
import com.alibaba.dubbo.common.logger.LoggerFactory;
import com.alibaba.dubbo.common.utils.ExecutorUtil;
import com.alibaba.dubbo.common.utils.NamedThreadFactory;
import com.alibaba.dubbo.common.utils.NetUtils;
import com.alibaba.dubbo.remoting.Channel;
import com.alibaba.dubbo.remoting.ChannelHandler;
import com.alibaba.dubbo.remoting.RemotingException;
import com.alibaba.dubbo.remoting.Server;
import com.alibaba.dubbo.remoting.transport.AbstractServer;
import com.alibaba.dubbo.remoting.transport.dispatcher.ChannelHandlers;
import java.net.InetSocketAddress;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
public class NettyServer extends AbstractServer implements Server {
private static final Logger logger = LoggerFactory.getLogger(NettyServer.class);
private Map channels;
private ServerBootstrap bootstrap;
private org.jboss.netty.channel.Channel channel;
public NettyServer(URL url, ChannelHandler handler) throws RemotingException {
super(url, ChannelHandlers.wrap(handler, ExecutorUtil.setThreadName(url, "DubboServerHandler")));
}
protected void doOpen() throws Throwable {
NettyHelper.setNettyLoggerFactory();
ExecutorService boss = Executors.newCachedThreadPool(new NamedThreadFactory("NettyServerBoss", true));
ExecutorService worker = Executors.newCachedThreadPool(new NamedThreadFactory("NettyServerWorker", true));
ChannelFactory channelFactory = new NioServerSocketChannelFactory(boss, worker, this.getUrl().getPositiveParameter("iothreads", Constants.DEFAULT_IO_THREADS));
this.bootstrap = new ServerBootstrap(channelFactory);
final NettyHandler nettyHandler = new NettyHandler(this.getUrl(), this);
this.channels = nettyHandler.getChannels();
this.bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() {
NettyCodecAdapter adapter = new NettyCodecAdapter(NettyServer.this.getCodec(), NettyServer.this.getUrl(), NettyServer.this);
ChannelPipeline pipeline = Channels.pipeline();
pipeline.addLast("decoder", adapter.getDecoder());
pipeline.addLast("encoder", adapter.getEncoder());
pipeline.addLast("handler", nettyHandler);
return pipeline;
}
});
this.channel = this.bootstrap.bind(this.getBindAddress());
}
protected void doClose() throws Throwable {
try {
if (this.channel != null) {
this.channel.close();
}
} catch (Throwable var8) {
logger.warn(var8.getMessage(), var8);
}
try {
Collection channels = this.getChannels();
if (channels != null && channels.size() > 0) {
Iterator i$ = channels.iterator();
while(i$.hasNext()) {
Channel channel = (Channel)i$.next();
try {
channel.close();
} catch (Throwable var7) {
logger.warn(var7.getMessage(), var7);
}
}
}
} catch (Throwable var9) {
logger.warn(var9.getMessage(), var9);
}
try {
if (this.bootstrap != null) {
this.bootstrap.releaseExternalResources();
}
} catch (Throwable var6) {
logger.warn(var6.getMessage(), var6);
}
try {
if (this.channels != null) {
this.channels.clear();
}
} catch (Throwable var5) {
logger.warn(var5.getMessage(), var5);
}
}
public Collection getChannels() {
Collection chs = new HashSet();
Iterator i$ = this.channels.values().iterator();
while(i$.hasNext()) {
Channel channel = (Channel)i$.next();
if (channel.isConnected()) {
chs.add(channel);
} else {
this.channels.remove(NetUtils.toAddressString(channel.getRemoteAddress()));
}
}
return chs;
}
public Channel getChannel(InetSocketAddress remoteAddress) {
return (Channel)this.channels.get(NetUtils.toAddressString(remoteAddress));
}
public boolean isBound() {
return this.channel.isBound();
}
}