网络编程 -- RPC实现原理 -- RPC -- 迭代版本V4 -- 远程方法调用 整合 Spring 自动注册

  • 阿里云国际版折扣https://www.yundadi.com

  • 阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

    网络编程 -- RPC实现原理 -- 目录

      啦啦啦

    V4——RPC -- 远程方法调用 + Spring 自动注册

      服务提供商:

        1. 配置 rpc04_server.xml 注入 服务提供商 rpcServiceProvider并指定初始化方法、销毁方法 及 服务实例 IUserService

        2. 读取 服务消费者 请求的 MethodStaics ,通过反射获取服务端实例方法的返回值。返回值为null值,则映射为NullWritable实例返回。不为null,则不加以约束。

      服务消费者:

        1. 配置 rpc04_client.xml 注入 服务注册类 ProxyBeanRegistry 并指定 服务提供商地址 及 注册服务 。

        2. 服务注册类 实现 BeanFactoryPostProcessor 接口,容器启动后 注入 RemoteRPCClient 实例 及 注册服务代理对象

    服务提供商:

      XML : rpc04_server.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans
    classpath:/org/springframework/beans/factory/xml/spring-beans-4.1.xsd
    http://www.springframework.org/schema/context
    classpath:/org/springframework/context/config/spring-context-4.1.xsd
    http://mybatis.org/schema/mybatis-spring
    http://mybatis.org/schema/mybatis-spring.xsd
    http://www.springframework.org/schema/aop
    classpath:org/springframework/aop/config/spring-aop-4.1.xsd"
    default-lazy-init="false"> <bean id="rpcServiceProvider" class="lime.pri.limeNio.netty.rpc04.core.server.RPCServiceProvider" >
    <constructor-arg index="0" value="9999"/>
    </bean> <bean id="IUserService" class="lime.pri.limeNio.netty.rpc04.service.impl.UserService"/> </beans>

      Class : RPCServiceProvider

    package lime.pri.limeNio.netty.rpc04.core.server;
    
    import java.lang.reflect.Method;
    import java.util.List; import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.DisposableBean;
    import org.springframework.beans.factory.InitializingBean;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware; import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.serializer.SerializerFeature; import io.netty.bootstrap.ServerBootstrap;
    import io.netty.buffer.ByteBuf;
    import io.netty.buffer.Unpooled;
    import io.netty.channel.ChannelFuture;
    import io.netty.channel.ChannelFutureListener;
    import io.netty.channel.ChannelHandlerAdapter;
    import io.netty.channel.ChannelHandlerContext;
    import io.netty.channel.ChannelInitializer;
    import io.netty.channel.ChannelPipeline;
    import io.netty.channel.EventLoopGroup;
    import io.netty.channel.nio.NioEventLoopGroup;
    import io.netty.channel.socket.SocketChannel;
    import io.netty.channel.socket.nio.NioServerSocketChannel;
    import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
    import io.netty.handler.codec.LengthFieldPrepender;
    import io.netty.handler.codec.MessageToMessageCodec;
    import io.netty.util.CharsetUtil;
    import lime.pri.limeNio.netty.rpc04.core.assist.MethodStaics;
    import lime.pri.limeNio.netty.rpc04.core.assist.NullWritable; public class RPCServiceProvider implements ApplicationContextAware, InitializingBean, DisposableBean { private ServerBootstrap serverBootstrap;
    private EventLoopGroup boss;
    private EventLoopGroup worker;
    private int port; private ApplicationContext act; public RPCServiceProvider() {
    super();
    } public RPCServiceProvider(int port) {
    this.serverBootstrap = new ServerBootstrap();
    this.boss = new NioEventLoopGroup();
    this.worker = new NioEventLoopGroup();
    this.serverBootstrap.group(boss, worker);
    this.serverBootstrap.channel(NioServerSocketChannel.class);
    this.port = port;
    } public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    this.act = applicationContext;
    } public void afterPropertiesSet() throws Exception {
    serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() { @Override
    protected void initChannel(SocketChannel ch) throws Exception {
    ChannelPipeline pipeline = ch.pipeline();
    pipeline.addLast(new LengthFieldPrepender(2))
    .addLast(new LengthFieldBasedFrameDecoder(65535, 0, 2, 0, 2))
    .addLast(new MessageToMessageCodec<ByteBuf, Object>() {
    @Override
    protected void encode(ChannelHandlerContext ctx, Object msg, List<Object> out)
    throws Exception {
    out.add(Unpooled.buffer()
    .writeBytes(JSON.toJSONString(msg, SerializerFeature.WriteClassName)
    .getBytes(CharsetUtil.UTF_8)));
    } @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out)
    throws Exception {
    out.add(JSON.parse(msg.toString(CharsetUtil.UTF_8)));
    }
    }).addLast(new ChannelHandlerAdapter() {
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    MethodStaics methodStaics = (MethodStaics) msg;
    Object invoke = null;
    try {
    Object bean = act.getBean(methodStaics.getTargetInterface());
    Method method = bean.getClass().getDeclaredMethod(methodStaics.getMethod(),
    methodStaics.getParameterTypes());
    invoke = method.invoke(bean, methodStaics.getArgs());
                          if(null == invoke)
                            throw new NullPointException();
    } catch (NullPointerException e) {
    //如果返回值为空,则返回NullWritable实例代替传输
                          invoke = new NullWritable();
    }
    ChannelFuture channelFuture = ctx.writeAndFlush(invoke);
    channelFuture.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
    channelFuture.addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
    channelFuture.addListener(ChannelFutureListener.CLOSE);
    } @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
    System.err.println(cause);
    }
    });
    }
    });
    /**
    * 绑定监听端口并启动服务 注意 : 启动的服务是阻塞的,防止阻塞Spring工厂采用异步启动
    */
    new Thread() {
    public void run() {
    try {
    System.out.println("服务启动@" + port + " ...");
    ChannelFuture channelFuture = serverBootstrap.bind(port).sync();
    channelFuture.channel().closeFuture().sync();
    } catch (InterruptedException e) {
    System.out.println(e);
    } finally {
    } };
    }.start();
    } public void destroy() throws Exception {
    boss.shutdownGracefully();
    worker.shutdownGracefully();
    }
    }

      Class : IUserService

    package lime.pri.limeNio.netty.rpc04.service;
    
    import java.util.List;
    
    import lime.pri.limeNio.netty.rpc04.entity.User;
    
    public interface IUserService {
    
        User queryById(Integer id);
    
        List<User> queryByName(String name);
    
        List<User> queryAll(Integer pageSize, Integer pageNum);
    }

      Class : UserService

    package lime.pri.limeNio.netty.rpc04.service.impl;
    
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    import java.util.concurrent.ConcurrentHashMap; import lime.pri.limeNio.netty.rpc04.entity.User;
    import lime.pri.limeNio.netty.rpc04.service.IUserService; public class UserService implements IUserService { private static Map<Integer, User> userMap = new ConcurrentHashMap<Integer, User>(); static {
    for (int i = 1; i <= 100; i++) {
    userMap.put(i, new User(i, "lime_" + i, new Date()));
    }
    } public User queryById(Integer id) {
    return userMap.get(id);
    } public List<User> queryAll(Integer pageSize, Integer pageNum) {
    int stNum = (pageNum - 1) * pageSize + 1;
    int enNum = pageNum * pageSize;
    List<User> result = new ArrayList<User>();
    for (int i = stNum; i <= enNum; i++) {
    result.add(userMap.get(i));
    }
    return result;
    } public static void main(String[] args) {
    UserService userService = new UserService();
    for (User user : userService.queryAll(10, 2)) {
    System.out.println(user);
    }
    System.out.println(userService.queryById(100));
    } public List<User> queryByName(String name) {
    List<User> result = null;
    Iterator<User> iterator = userMap.values().iterator();
    while (iterator.hasNext()) {
    User user = iterator.next();
    if (user.getName().equals(name)) {
    if (null == result)
    result = new ArrayList<User>();
    result.add(user);
    }
    }
    return result;
    } }

    服务消费者:

      XML : rpc04_client.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans
    classpath:/org/springframework/beans/factory/xml/spring-beans-4.1.xsd
    http://www.springframework.org/schema/context
    classpath:/org/springframework/context/config/spring-context-4.1.xsd
    http://mybatis.org/schema/mybatis-spring
    http://mybatis.org/schema/mybatis-spring.xsd
    http://www.springframework.org/schema/aop
    classpath:org/springframework/aop/config/spring-aop-4.1.xsd"
    default-lazy-init="false"> <bean class="lime.pri.limeNio.netty.rpc04.core.registry.ProxyBeanRegistry">
    <constructor-arg index="0">
    <bean class="lime.pri.limeNio.netty.rpc04.core.client.assist.HostAndPort">
    <constructor-arg index="0" value="127.0.0.1" />
    <constructor-arg index="1" value="9999" />
    </bean>
    </constructor-arg>
    <property name="proxyBeanMap">
    <map>
    <entry key="userService" value="lime.pri.limeNio.netty.rpc04.service.IUserService" />
    <entry key="personService" value="lime.pri.limeNio.netty.rpc04.service.IUserService" />
    </map>
    </property>
    </bean> </beans>

      Class : ProxyBeanRegistry

    package lime.pri.limeNio.netty.rpc04.core.registry;
    
    import java.util.Map;
    
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
    import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
    import org.springframework.beans.factory.support.AbstractBeanDefinition;
    import org.springframework.beans.factory.support.BeanDefinitionBuilder;
    import org.springframework.beans.factory.support.DefaultListableBeanFactory;
    import org.springframework.util.CollectionUtils; import lime.pri.limeNio.netty.rpc04.core.client.assist.HostAndPort;
    import lime.pri.limeNio.netty.rpc04.core.client.proxy.RPCObjectProxy;
    import lime.pri.limeNio.netty.rpc04.core.client.rpcClient.impl.RemoteRPCClient; /**
    * 通过postProcessBeanFactory()向beanFactory注册实体Bean
    *
    * @author lime
    *
    */
    public class ProxyBeanRegistry implements BeanFactoryPostProcessor { private Map<String, Class<?>> proxyBeanMap;
    private HostAndPort hap; public ProxyBeanRegistry() {
    super();
    } public ProxyBeanRegistry(HostAndPort hap) {
    super();
    this.hap = hap;
    } public void postProcessBeanFactory(ConfigurableListableBeanFactory listableBeanFactory) throws BeansException {
    DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) listableBeanFactory;
    // 配置RemoteRPCClient实例:HostAndPort
    BeanDefinitionBuilder remoteRPCClient = BeanDefinitionBuilder.genericBeanDefinition(RemoteRPCClient.class);
    remoteRPCClient.addConstructorArgValue(hap);
    AbstractBeanDefinition remoteRPCClientBeanDefinition = remoteRPCClient.getBeanDefinition();
    defaultListableBeanFactory.registerBeanDefinition("remoteRPCClient", remoteRPCClientBeanDefinition); // 配置RPCObjectProxy实例:注册的接口、服务消费者
    if(!CollectionUtils.isEmpty(proxyBeanMap)){
    for(Map.Entry<String, Class<?>> entry : proxyBeanMap.entrySet()){
    String beanName = entry.getKey(); //注册Bean的名字
    Class<?> beanClazz = entry.getValue(); //需要代理的接口
    BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(RPCObjectProxy.class);
    beanDefinitionBuilder.addConstructorArgReference("remoteRPCClient");
    beanDefinitionBuilder.addConstructorArgValue(beanClazz);
    AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
    defaultListableBeanFactory.registerBeanDefinition(beanName, beanDefinition);
    }
    }
    } public void setProxyBeanMap(Map<String, Class<?>> proxyBeanMap) {
    this.proxyBeanMap = proxyBeanMap;
    } }

     Class : RPCClient

    package lime.pri.limeNio.netty.rpc04.core.client.rpcClient;
    
    import org.springframework.beans.factory.DisposableBean;
    
    import lime.pri.limeNio.netty.rpc04.core.assist.MethodStaics;
    
    /**
    * 通过RPCClient实现对远程方法的调用
    *
    * @author lime
    *
    */
    public interface RPCClient extends DisposableBean { Object invokeMethod(MethodStaics methodStaics); }

      Class : RemoteRPCClient

    package lime.pri.limeNio.netty.rpc04.core.client.rpcClient.impl;
    
    import java.net.InetSocketAddress;
    import java.util.List; import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.serializer.SerializerFeature; import io.netty.bootstrap.Bootstrap;
    import io.netty.buffer.ByteBuf;
    import io.netty.buffer.Unpooled;
    import io.netty.channel.ChannelFuture;
    import io.netty.channel.ChannelFutureListener;
    import io.netty.channel.ChannelHandlerAdapter;
    import io.netty.channel.ChannelHandlerContext;
    import io.netty.channel.ChannelInitializer;
    import io.netty.channel.ChannelPipeline;
    import io.netty.channel.EventLoopGroup;
    import io.netty.channel.nio.NioEventLoopGroup;
    import io.netty.channel.socket.SocketChannel;
    import io.netty.channel.socket.nio.NioSocketChannel;
    import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
    import io.netty.handler.codec.LengthFieldPrepender;
    import io.netty.handler.codec.MessageToMessageCodec;
    import io.netty.util.CharsetUtil;
    import lime.pri.limeNio.netty.rpc04.core.assist.MethodStaics;
    import lime.pri.limeNio.netty.rpc04.core.assist.NullWritable;
    import lime.pri.limeNio.netty.rpc04.core.client.assist.HostAndPort;
    import lime.pri.limeNio.netty.rpc04.core.client.rpcClient.RPCClient; /**
    * 通过TCP/IP协议实现远程方法调用
    *
    * @author lime
    *
    */
    public class RemoteRPCClient implements RPCClient { private Bootstrap bootstrap;
    private EventLoopGroup worker;
    private HostAndPort hostAndPort; public RemoteRPCClient() {
    super();
    } public RemoteRPCClient(HostAndPort hostAndPost) {
    this.hostAndPort = hostAndPost;
    // 初始化数据
    this.bootstrap = new Bootstrap();
    this.worker = new NioEventLoopGroup();
    this.bootstrap.group(this.worker);
    this.bootstrap.channel(NioSocketChannel.class);
    } public Object invokeMethod(final MethodStaics methodStaics) {
    bootstrap.handler(new ChannelInitializer<SocketChannel>() {
    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
    ChannelPipeline pipeline = ch.pipeline();
    pipeline.addLast(new LengthFieldBasedFrameDecoder(65535, 0, 2, 0, 2))
    .addLast(new LengthFieldPrepender(2)).addLast(new MessageToMessageCodec<ByteBuf, Object>() {
    @Override
    protected void encode(ChannelHandlerContext ctx, Object msg, List<Object> out)
    throws Exception {
    out.add(Unpooled.buffer()
    .writeBytes(JSON.toJSONString(msg, SerializerFeature.WriteClassName)
    .getBytes(CharsetUtil.UTF_8)));
    } @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out)
    throws Exception {
    out.add(JSON.parse(msg.toString(CharsetUtil.UTF_8)));
    }
    }).addLast(new ChannelHandlerAdapter() {
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
    ChannelFuture channelFuture = ctx.writeAndFlush(methodStaics);
    channelFuture.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
    channelFuture.addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
    } @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    methodStaics.setResult(msg);
    } @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
    System.err.println(cause);
    }
    });
    }
    });
    ChannelFuture channelFuture;
    try {
    channelFuture = bootstrap.connect(new InetSocketAddress(hostAndPort.getHost(), hostAndPort.getPort()))
    .sync();
    channelFuture.channel().closeFuture().sync();
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    // 服务端返回值为null,处理方式
    return methodStaics.getResult() instanceof NullWritable ? null : methodStaics.getResult();
    } public void destroy() throws Exception {
    worker.shutdownGracefully();
    }
    }

      Class : RPCObjectProxy

    package lime.pri.limeNio.netty.rpc04.core.client.proxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy; import org.springframework.beans.factory.FactoryBean; import lime.pri.limeNio.netty.rpc04.core.assist.MethodStaics;
    import lime.pri.limeNio.netty.rpc04.core.client.rpcClient.RPCClient; /**
    * 通过接口动态创建代理对象
    *
    * @author lime
    * @param <T>
    *
    * 实现FactoryBean接口,与Spring整合
    *
    */
    public class RPCObjectProxy implements InvocationHandler, FactoryBean<Object> { private RPCClient rpcClient;
    private Class<?> targetInterface; public RPCObjectProxy() {
    super();
    } public RPCObjectProxy(RPCClient rpcClient, Class<?> targetInterface) {
    super();
    this.rpcClient = rpcClient;
    this.targetInterface = targetInterface;
    } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    return rpcClient
    .invokeMethod(new MethodStaics(targetInterface, method.getName(), args, method.getParameterTypes()));
    } // 产生代理对象
    public Object getObject() throws Exception {
    return Proxy.newProxyInstance(RPCObjectProxy.class.getClassLoader(), new Class[] { targetInterface }, this); } public Class<?> getObjectType() {
    return targetInterface;
    } public boolean isSingleton() {
    return true;
    }
    }

      Class : HostAndPort

    package lime.pri.limeNio.netty.rpc04.core.client.assist;
    
    import java.io.Serializable;
    
    public class HostAndPort implements Serializable{
    
        /**
    *
    */
    private static final long serialVersionUID = 1L; private String host;
    private int port;
    public HostAndPort() {
    super();
    // TODO Auto-generated constructor stub
    }
    public HostAndPort(String host, int port) {
    super();
    this.host = host;
    this.port = port;
    }
    public String getHost() {
    return host;
    }
    public void setHost(String host) {
    this.host = host;
    }
    public int getPort() {
    return port;
    }
    public void setPort(int port) {
    this.port = port;
    }
    @Override
    public String toString() {
    return "HostAndPort [host=" + host + ", port=" + port + "]";
    } }

    辅助类 :

      Class : MethodStaics

    package lime.pri.limeNio.netty.rpc04.core.assist;
    
    import java.io.Serializable;
    import java.util.Arrays; /**
    * @author lime
    *
    */
    public class MethodStaics implements Serializable{ /**
    *
    */
    private static final long serialVersionUID = 1L;
    private Class<?> targetInterface;
    private String method;
    private Object[] args;
    private Class[] parameterTypes;
    private Object result;
    public MethodStaics() {
    super();
    // TODO Auto-generated constructor stub
    }
    public MethodStaics(Class<?> targetInterface, String method, Object[] args, Class[] parameterTypes) {
    super();
    this.targetInterface = targetInterface;
    this.method = method;
    this.args = args;
    this.parameterTypes = parameterTypes;
    }
    @Override
    public String toString() {
    return "MethodStaics [targetInterface=" + targetInterface + ", method=" + method + ", args="
    + Arrays.toString(args) + ", parameterTypes=" + Arrays.toString(parameterTypes) + "]";
    }
    public Class<?> getTargetInterface() {
    return targetInterface;
    }
    public void setTargetInterface(Class<?> targetInterface) {
    this.targetInterface = targetInterface;
    }
    public String getMethod() {
    return method;
    }
    public void setMethod(String method) {
    this.method = method;
    }
    public Object[] getArgs() {
    return args;
    }
    public void setArgs(Object[] args) {
    this.args = args;
    }
    public Class[] getParameterTypes() {
    return parameterTypes;
    }
    public void setParameterTypes(Class[] parameterTypes) {
    this.parameterTypes = parameterTypes;
    }
    public Object getResult() {
    return result;
    }
    public void setResult(Object result) {
    this.result = result;
    } }

      Class : NullWritable

    package lime.pri.limeNio.netty.rpc04.core.assist;
    
    import java.io.Serializable;
    
    public class NullWritable implements Serializable{
    
        /**
    *
    */
    private static final long serialVersionUID = 1L; }

      Class : User

    package lime.pri.limeNio.netty.rpc04.entity;
    
    import java.io.Serializable;
    import java.util.Date; public class User implements Serializable{ /**
    *
    */
    private static final long serialVersionUID = 1L; private int id;
    private String name;
    private Date birth;
    public User() {
    super();
    // TODO Auto-generated constructor stub
    }
    public User(int id, String name, Date birth) {
    super();
    this.id = id;
    this.name = name;
    this.birth = birth;
    }
    @Override
    public String toString() {
    return "User [id=" + id + ", name=" + name + ", birth=" + birth + "]";
    }
    public int getId() {
    return id;
    }
    public void setId(int id) {
    this.id = id;
    }
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }
    public Date getBirth() {
    return birth;
    }
    public void setBirth(Date birth) {
    this.birth = birth;
    } }

    测试类 :

      Class : TtServer

    package lime.pri.limeNio.netty.rpc04.tT;
    
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class TtServer {
    
        public static void main(String[] args) throws Exception {
    new ClassPathXmlApplicationContext("classpath:spring/rpc04_server.xml");
    }
    }

      Class :

    package lime.pri.limeNio.netty.rpc04.tT;
    
    import java.util.List;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext; import lime.pri.limeNio.netty.rpc04.entity.User;
    import lime.pri.limeNio.netty.rpc04.service.IUserService; public class TtClient { public static void main(String[] args) throws Exception {
    ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:spring/rpc04_client.xml");
    IUserService userService = (IUserService) ctx.getBean("userService");
    User user = userService.queryById(23);
    System.out.println(user);
    System.out.println("-- --");
    IUserService personService = (IUserService) ctx.getBean("personService");
    List<User> list = personService.queryAll(10, 4);
    for(User u : list){
    System.out.println(u);
    }
    }
    }

      Console : Server

    六月 25, 2017 3:35:47 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
    信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@17f052a3: startup date [Sun Jun 25 15:35:47 CST 2017]; root of context hierarchy
    六月 25, 2017 3:35:47 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
    信息: Loading XML bean definitions from class path resource [spring/rpc04_server.xml]
    服务启动@9999 ...

      Console : Client

    六月 25, 2017 3:52:39 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
    信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@17f052a3: startup date [Sun Jun 25 15:52:39 CST 2017]; root of context hierarchy
    六月 25, 2017 3:52:39 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
    信息: Loading XML bean definitions from class path resource [spring/rpc04_client.xml]
    User [id=23, name=lime_23, birth=Sun Jun 25 15:52:10 CST 2017]
    -- --
    User [id=31, name=lime_31, birth=Sun Jun 25 15:52:10 CST 2017]
    User [id=32, name=lime_32, birth=Sun Jun 25 15:52:10 CST 2017]
    User [id=33, name=lime_33, birth=Sun Jun 25 15:52:10 CST 2017]
    User [id=34, name=lime_34, birth=Sun Jun 25 15:52:10 CST 2017]
    User [id=35, name=lime_35, birth=Sun Jun 25 15:52:10 CST 2017]
    User [id=36, name=lime_36, birth=Sun Jun 25 15:52:10 CST 2017]
    User [id=37, name=lime_37, birth=Sun Jun 25 15:52:10 CST 2017]
    User [id=38, name=lime_38, birth=Sun Jun 25 15:52:10 CST 2017]
    User [id=39, name=lime_39, birth=Sun Jun 25 15:52:10 CST 2017]
    User [id=40, name=lime_40, birth=Sun Jun 25 15:52:10 CST 2017]
    -- --
    null
    -- --

    啦啦啦

  • 阿里云国际版折扣https://www.yundadi.com

  • 阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
    标签: Spring

    “网络编程 -- RPC实现原理 -- RPC -- 迭代版本V4 -- 远程方法调用 整合 Spring 自动注册” 的相关文章

    PHP中怎么使用字符正则替换字符串 - 编程语言

    这篇文章主要介绍了PHP中怎么使用字符正则替换字符串的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇PHP中怎么使用字符正则替换字符串文章都会有所收获,下面我们一起来看看吧。 首先,我们需要了解正则表达式的基础知...

    Python网络爬虫之HTTP原理是什么 - 开发技术

    今天小编给大家分享一下Python网络爬虫之HTTP原理是什么的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。HTTP 基本原理在本文中,我们会详细了解...

    Docker:关于 Dockerfile 编写优化的一些笔记整理

    写在前面 分享一些 Dickerfile 构建镜像优化方式的笔记 理解不足小伙伴帮忙指正 对每个人而言,真正的职责只有一个:找到自我。然后在心中坚守其一生,全心全意,永不停息。所有其它的路都是不完整...

    Vue处理循环数据流程的代码怎么写 - 开发技术

    这篇文章主要介绍了Vue处理循环数据流程的代码怎么写的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Vue处理循环数据流程的代码怎么写文章都会有所收获,下面我们一起来看看吧。下面就展示使用vue处理循环的一个例子,首先声明,这个例子使用的是...

    aop注解简单日志

    mport java.lang.reflect.Method; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotati...

    vue的两种路由模式源码分析 - 编程语言

    这篇文章主要介绍“vue的两种路由模式源码分析”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“vue的两种路由模式源码分析”文章能帮助大家解决问题。 哈希模式(hash)vue-router默认has...