概述
这里只讲解dubbo注册的bean
1. dubbo consumer 加载bean
dubbo-2.5.3.jar!/spring.handlers
http://code.alibabatech.com/schema/dubbo=com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler
DubboNamespaceHandler 是dubbo命名空间自定义配置文件的解析处理器
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));
}
}
spring会根据xml的命名空间调用响应的Parser进行处理,进入 DubboBeanDefinitionParser的解析parse
private static BeanDefinition parse(Element element, ParserContext parserContext, Class<?> beanClass, boolean required) {
RootBeanDefinition beanDefinition = new RootBeanDefinition();
beanDefinition.setBeanClass(beanClass);
beanDefinition.setLazyInit(false);
String id = element.getAttribute("id");
省略....
if (id != null && id.length() > 0) {
if (parserContext.getRegistry().containsBeanDefinition(id)) {
throw new IllegalStateException("Duplicate spring bean id " + id);
}
parserContext.getRegistry().registerBeanDefinition(id, beanDefinition);//这里调用了bean的注册
beanDefinition.getPropertyValues().addPropertyValue("id", id);
}
省略....
}
这一步注意,虽然注册的bean id(如 demoService) 是与privider端的service的id相同的,但是这里beanDefinition的beanClass却不是自己定义的某个接口了。
在spring解析配置beans时先生成bean的定义,然后getBean时,是通过className获取Class,然后设置bd.setBeanClass(class)
org.springframework.beans.factory.support.AbstractBeanFactory
private Class<?> doResolveBeanClass(RootBeanDefinition mbd, Class<?>... typesToMatch) throws ClassNotFoundException {
if (!ObjectUtils.isEmpty(typesToMatch)) {
ClassLoader tempClassLoader = getTempClassLoader();
if (tempClassLoader != null) {
if (tempClassLoader instanceof DecoratingClassLoader) {
DecoratingClassLoader dcl = (DecoratingClassLoader) tempClassLoader;
for (Class<?> typeToMatch : typesToMatch) {
dcl.excludeClass(typeToMatch.getName());
}
}
String className = mbd.getBeanClassName();
return (className != null ? ClassUtils.forName(className, tempClassLoader) : null);
}
}
return mbd.resolveBeanClass(getBeanClassLoader());
}
在执行
registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, false));
时已经将 DubboBeanDefinitionParser.beanClass = ReferenceBean.class
故在解析时实际是如下形式
RootBeanDefinition beanDefinition = new RootBeanDefinition();
beanDefinition.setBeanClass(beanClass); //ReferenceBean.class
beanDefinition.setLazyInit(false);
即将id=demoService 与 类
ReferenceBean
绑定,放入map, 即使用的是FactoryBean来创建bean
当spring使用getBean(‘demoService“) 会调用工厂bean的getObject : ReferenceBean.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;
}
private void init() {
if (initialized) {
return;
}
initialized = true;
省略....
ref = createProxy(map);//在这里使用了动态代理生成对象
}
ref = createProxy(map);//在这里使用了动态代理生成了代理对象(这里也可以成为远程代理,因为在这个代理中进行了远程调用),ref 即getBean返回的对象,这样在action调用demoService是就会使用代理处理器com.alibaba.dubbo.rpc.proxy.InvokerInvocationHandler
public class InvokerInvocationHandler implements InvocationHandler {
private final Invoker<?> invoker;
public InvokerInvocationHandler(Invoker<?> handler){
this.invoker = handler;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
Class<?>[] parameterTypes = method.getParameterTypes();
if (method.getDeclaringClass() == Object.class) {
return method.invoke(invoker, args);
}
if ("toString".equals(methodName) && parameterTypes.length == 0) {
return invoker.toString();
}
if ("hashCode".equals(methodName) && parameterTypes.length == 0) {
return invoker.hashCode();
}
if ("equals".equals(methodName) && parameterTypes.length == 1) {
return invoker.equals(args[0]);
}
return invoker.invoke(new RpcInvocation(method, args)).recreate();
}
}
看最后一句 invoker.invoke(new RpcInvocation(method, args)).recreate(); 这里就开始进入调用远程的服务
最后
以上就是复杂小懒猪为你收集整理的dubbo 加载Bean和远程调用分析(1)的全部内容,希望文章能够帮你解决dubbo 加载Bean和远程调用分析(1)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复