動態代理的簡單實用

這兩天在研讀大衆點評所採用的分佈式任務調度系統,發現了許雪裏的許多值得我學習的代碼。其中讓我印象最深的就是調度中心向執行器分發任務的代碼,在執行器和調度中心之間的通信使用的是內置的jetty服務器(總感覺netty更好一點,畢竟是傳輸層)。

調度中心使用動態代理,在執行某服務的方法的過程中,通過反射的方式獲得要執行的方法名, 方法參數然後將其 封裝爲一個request 傳遞給執行器,執行器再對調度中心的request進行解析,通過反射來執行相應的任務。

在這裏簡單模擬了一下:

/**
 *
 * @author xiaosuda
 * @date 2018/2/6
 */
public class MastNode {

    public static void main(String [] args){
        MastNode mastNode = new MastNode();
        ProxyFactory proxyFactory = mastNode.new ProxyFactory(new BirdServiceImpl(), BirdService.class);
        BirdService proxy = (BirdService) proxyFactory.getProxy();
        System.out.println(proxy.say("嘰嘰喳喳", 6));
        System.out.println(proxy.walk(5));

    }

    class ProxyFactory {
        private Object obj;
        private Class< ? extends Object> cla;

        public ProxyFactory(Object obj, Class< ? extends Object> cla){
            this.obj = obj;
            this.cla = cla;
        }

        public Object getProxy() {
            return Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[] { cla }, new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    RpcRequest rpcRequest = new RpcRequest();
                    rpcRequest.setServiceBean(obj);
                    rpcRequest.setMethodName(method.getName());
                    rpcRequest.setParameterTypes(method.getParameterTypes());
                    rpcRequest.setParameters(args);

                    WorkNode workNode = new WorkNode();
                    return workNode.executeRpcMethod(rpcRequest);
                }
            });
        }
    }
}


class WorkNode {
    public Object executeRpcMethod(RpcRequest request) throws InvocationTargetException {
        String methodName = request.getMethodName();
        Class<?>[] parameterTypes = request.getParameterTypes();
        Object[] parameters = request.getParameters();
        Object serviceBean = request.getServiceBean();
        FastClass serviceFastClass = FastClass.create(serviceBean.getClass());
        FastMethod serviceFastClassMethod = serviceFastClass.getMethod(methodName, parameterTypes);
        Object result = serviceFastClassMethod.invoke(serviceBean, parameters);
        return "遠程執行結果:{" + result + "}";

    }
}

class RpcRequest {
    private Object serviceBean;
    private String methodName;
    private Class<?>[] parameterTypes;
    private Object[] parameters;

    public void setServiceBean(Object serviceBean) {
        this.serviceBean = serviceBean;
    }

    public Object getServiceBean() {
        return serviceBean;
    }

    public String getMethodName() {
        return methodName;
    }

    public void setMethodName(String methodName) {
        this.methodName = methodName;
    }

    public Class<?>[] getParameterTypes() {
        return parameterTypes;
    }

    public void setParameterTypes(Class<?>[] parameterTypes) {
        this.parameterTypes = parameterTypes;
    }

    public Object[] getParameters() {
        return parameters;
    }

    public void setParameters(Object[] parameters) {
        this.parameters = parameters;
    }
}

class BirdServiceImpl implements BirdService{
    @Override
    public String say(String content, Integer times) {

        for (int i = 0; i < times; i++) {
            System.out.println(content + " ");
        }

        StringBuilder sb = new StringBuilder();
        sb.append("該小鳥鳴叫內容:").append(content).append(",鳴叫次數:").append(times);
        return sb.toString();
    }

    @Override
    public String walk(Integer steps) {
        for (int i = 0; i < steps; i++) {
            System.out.println("行走一步");
        }

        StringBuilder sb = new StringBuilder();
        sb.append("該小鳥行走了").append(steps).append("步");
        return sb.toString();
    }
}

interface BirdService {
    /**
     *
     * @param content
     * @param times
     * @return
     */
    String say(String content, Integer times);

    /**
     *
     * @param steps
     * @return
     */
    String walk(Integer steps);

執行結果:

嘰嘰喳喳 
嘰嘰喳喳 
嘰嘰喳喳 
嘰嘰喳喳 
嘰嘰喳喳 
嘰嘰喳喳 
遠程執行結果:{該小鳥鳴叫內容:嘰嘰喳喳,鳴叫次數:6}
行走一步
行走一步
行走一步
行走一步
行走一步
遠程執行結果:{該小鳥行走了5步}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章