1)解析ReferenceBean的各种属性的过程是类似的:
String value = element.getAttribute(property);
Object reference = new RuntimeBeanReference(value);
beanDefinition.getPropertyValues().addPropertyValue(property, reference);
public class ReferenceBean<T> extends ReferenceConfig<T> implements FactoryBean, ApplicationContextAware, InitializingBean, DisposableBean
我们看到 ReferenceBean还实现了FactoryBean接口(getObject等方法),这显然是必须的,ReferenceBean不就是要拿到远程服务对象的代理嘛。查看代码,是的,这个
getObject方法正是入口。
T ref = createProxy(map);
return ref;
2)来看看createProxy(map):
if (isJvmRefer) {//默认情况下如果本地有服务暴露,则引用本地服务.
URL url = new URL(Constants.LOCAL_PROTOCOL, NetUtils.LOCALHOST, 0, interfaceClass.getName()).addParameters(map);
invoker = refprotocol.refer(interfaceClass, url);
} else {
invoker = refprotocol.refer(interfaceClass, urls.get(0));//先看单个的,cluster无非是根据策略从多个中选一个
}
// 创建服务代理
return (T) proxyFactory.getProxy(invoker);//此方法在2中已列出,这里不再重复分析。
这样,客户consumer程序就可以利用代理调用目标对象的方法了。
3)具体分析一下拿到invoker的过程:
refprotocol.refer(interfaceClass, url);
public <T> Invoker<T> refer(final Class<T> type, final URL url) throws RpcException {
final Invoker<T> tagert = proxyFactory.getInvoker(doRefer(type, url), type, url);
Invoker<T> invoker = new AbstractInvoker<T>(type, url) {
@Override
protected Result doInvoke(Invocation invocation) throws Throwable {
try {
Result result = tagert.invoke(invocation);
Throwable e = result.getException();
if (e != null) {
for (Class<?> rpcException : rpcExceptions) {
if (rpcException.isAssignableFrom(e.getClass())) {
throw getRpcException(type, url, invocation, e);
}
}
}
return result;
} catch (RpcException e) {
if (e.getCode() == RpcException.UNKNOWN_EXCEPTION) {
e.setCode(getErrorCode(e.getCause()));
}
throw e;
} catch (Throwable e) {
throw getRpcException(type, url, invocation, e);
}
}
};
invokers.add(invoker);
return invoker;
}
protected <T> T doRefer(final Class<T> serviceType, final URL url) throws RpcException {
final RmiProxyFactoryBean rmiProxyFactoryBean = new RmiProxyFactoryBean();
rmiProxyFactoryBean.setServiceUrl(url.toIdentityString());
rmiProxyFactoryBean.setServiceInterface(serviceType);
rmiProxyFactoryBean.setCacheStub(true);
rmiProxyFactoryBean.setLookupStubOnStartup(true);
rmiProxyFactoryBean.setRefreshStubOnConnectFailure(true);
rmiProxyFactoryBean.afterPropertiesSet();
return (T) rmiProxyFactoryBean.getObject();
}
仍然以rmi协议为例,这里用了spring里线程的RmiProxyFactoryBean来生成rmi协议的代理对象。
如果是自定义协议如dubbo,那就得自行实现类似的过程。我们下一节准备来看看dubbo协议的export(), refer()的实现