dubbo invoker

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.rpc;

import com.alibaba.dubbo.common.Node;

/**
 * Invoker. (API/SPI, Prototype, ThreadSafe)
 *
 * @see com.alibaba.dubbo.rpc.Protocol#refer(Class, com.alibaba.dubbo.common.URL)
 * @see com.alibaba.dubbo.rpc.InvokerListener
 * @see com.alibaba.dubbo.rpc.protocol.AbstractInvoker
 */
public interface Invoker<T> extends Node {

    /**
     * get service interface.
     *
     * @return service interface.
     */
    Class<T> getInterface();

    /**
     * invoke.
     *
     * @param invocation
     * @return result
     * @throws RpcException
     */
    Result invoke(Invocation invocation) throws RpcException;

}

dubbo中通过将每一个服务类(Service)包装成一个Invoker对象,然后通过协议(比如RMI)发送到网络。这样每个协议类不需要面对各种不同的服务类了。

下面示例说明Invoker的作用:

首先创建一个服务接口类

package com.enjoy.service;

public interface DemoService {
    String sayHello(String name);
}

为该类创建一个实现类

package com.enjoy.service;

public class DemoServiceImpl implements DemoService {
	private String type = "test";

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}

	public DemoServiceImpl() {
		super();
	}

	public String sayHello(String name) {
		System.out.println("hello " + name + ", type:" + type);
		return "Hello, " + name;
	}

}

实现一个Invoker类

package com.enjoy.protocol;

import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Result;
import com.alibaba.dubbo.rpc.RpcException;
import com.alibaba.dubbo.rpc.RpcResult;
import com.enjoy.service.DemoService;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * SimpleInvoker.
 */
public class SimpleInvoker<T> implements Invoker<T> {
	private T target;
	private Class<T> type;
	private URL url;

	public SimpleInvoker(T service, Class<T> type, URL url) {
		this.target = service;
		this.type = type;
		this.url = url;
	}

	@Override
	public Class<T> getInterface() {
		return type;
	}

	@Override
	public Result invoke(Invocation invocation) throws RpcException {
		Method method = null;
		try {
			method = type.getMethod(invocation.getMethodName(), invocation.getParameterTypes());
			return new RpcResult(method.invoke(target, invocation.getArguments()));
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public URL getUrl() {
		return url;
	}

	@Override
	public boolean isAvailable() {
		return true;
	}

	@Override
	public void destroy() {

	}

}

创建一个动态代理类

package com.alibaba.dubbo.rpc.proxy;

import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.RpcInvocation;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * InvokerHandler
 */
public class InvokerInvocationHandler implements InvocationHandler {
	// 真实对象为Invoker对象
    private final Invoker<?> invoker;

    public InvokerInvocationHandler(Invoker<?> handler) {
        this.invoker = handler;
    }

    @Override
    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]);
        }
        // 执行invoker方法
        return invoker.invoke(new RpcInvocation(method, args)).recreate();
    }

}

实现一个protocol类(rmi)

package com.enjoy.protocol;

import java.lang.reflect.Proxy;
import java.rmi.RemoteException;

import org.aopalliance.intercept.MethodInvocation;
import org.springframework.remoting.rmi.RmiProxyFactoryBean;
import org.springframework.remoting.rmi.RmiServiceExporter;
import org.springframework.remoting.support.RemoteInvocation;
import org.springframework.remoting.support.RemoteInvocationFactory;

import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.common.Version;
import com.alibaba.dubbo.rpc.Exporter;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Protocol;
import com.alibaba.dubbo.rpc.RpcException;
import com.alibaba.dubbo.rpc.protocol.rmi.RmiRemoteInvocation;
import com.alibaba.dubbo.rpc.proxy.InvokerInvocationHandler;

/**
 * RmiProtocol.
 */
public class RmiProtocol implements Protocol {

	public static final int DEFAULT_PORT = 1099;

	@Override
	public int getDefaultPort() {
		return DEFAULT_PORT;
	}

	@Override
	public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
		// 创建spring rmi服务
		final RmiServiceExporter rmiServiceExporter = new RmiServiceExporter();
		rmiServiceExporter.setRegistryPort(invoker.getUrl().getPort());
		rmiServiceExporter.setServiceName(invoker.getUrl().getPath());
		rmiServiceExporter.setServiceInterface(invoker.getInterface());

		// 此时目标服务没有,需要通过invoker调通,使用代理 创建一个动态代理
		T service = (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
				new Class[] { invoker.getInterface() }, new InvokerInvocationHandler(invoker));

		rmiServiceExporter.setService(service);// DemoService service,如果能拿它,直接设入就ok
		try {
			rmiServiceExporter.afterPropertiesSet();
		} catch (RemoteException e) {
			throw new RpcException(e.getMessage(), e);
		}
		return null;
	}

	@Override
	public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
        T obj = doRefer(type, url);
		return new SimpleInvoker(obj, type, url);
	}

    // 客户端
	public <T> T doRefer(Class<T> type, URL url) throws RpcException {
		final RmiProxyFactoryBean rmiProxyFactoryBean = new RmiProxyFactoryBean();
		// 使用dubbo协议
        if (url.getParameter(Constants.DUBBO_VERSION_KEY, Version.getProtocolVersion())
				.equals(Version.getProtocolVersion())) {
			rmiProxyFactoryBean.setRemoteInvocationFactory(new RemoteInvocationFactory() {
				@Override
				public RemoteInvocation createRemoteInvocation(MethodInvocation methodInvocation) {
					return new RmiRemoteInvocation(methodInvocation);
				}
			});
		}
		rmiProxyFactoryBean.setServiceUrl(url.toIdentityString());
		rmiProxyFactoryBean.setServiceInterface(type);
		rmiProxyFactoryBean.setCacheStub(true);
		rmiProxyFactoryBean.setLookupStubOnStartup(true);
		rmiProxyFactoryBean.setRefreshStubOnConnectFailure(true);
		rmiProxyFactoryBean.afterPropertiesSet();
        // 使用spring rmi远程调用
		return (T) rmiProxyFactoryBean.getObject();
	}

	@Override
	public void destroy() {
	}
}

调用逻辑

package com.enjoy;

import java.io.IOException;
import java.lang.reflect.Proxy;

import org.junit.Test;

import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Protocol;
import com.alibaba.dubbo.rpc.proxy.InvokerInvocationHandler;
import com.enjoy.protocol.RmiProtocol;
import com.enjoy.protocol.SimpleInvoker;
import com.enjoy.service.DemoService;
import com.enjoy.service.DemoServiceImpl;

public class RpcProtocolTest {
    URL url = URL.valueOf("rmi://127.0.0.1:9001/"+ DemoService.class.getName());

    /**
     * 服务端 invoker->protocol
     * Protocol连接服务端invoker
     * 将目标服务调用信息,包装成为invoker实体,暴露到网络上
     *
     * 当网络信息到达,将触发invoker的invoke方法,最终将调用转到目标service上
     */
    @Test
    public void invoker2protocol() throws IOException {
        DemoService service = new DemoServiceImpl();
        // 将服务类包装到Invoker对象中
        Invoker<DemoService> invoker = new SimpleInvoker(service,DemoService.class,url);
        Protocol protocol = new RmiProtocol();
        //暴露对象
        protocol.export(invoker);
        System.out.println("Dubbo server 启动");
        // 保证服务一直开着
        System.in.read();
    }

    /**
     * Protocol连接消费端invoker
     * 将要调用的信息,包装成invoker实体,向网络发送
     *
     * 本地调用接口代理时,最终方法被转到invoker的invoke方法上,向网络发送
     */
    @Test
    public void protocol2Invoker() {
        //协议
        Protocol protocol = new RmiProtocol();
        //消费invoker,负责发送协议调用信息 也是创建一个Invoker
        Invoker<DemoService> invoker = protocol.refer(DemoService.class, url);
        //做一个动态代理,将调用目标指向invoker即可
        DemoService service = (DemoService)Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                new Class[]{invoker.getInterface()},
                new InvokerInvocationHandler(invoker));//反射逻辑
        // 上面只是生成了一个代理,实际执行方法时才会真实调用,触发invoker
        String result = service.sayHello("peter");
        System.out.println(result);
    }
}

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lang20150928

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值