• 【spring源码学习】spring的远程调用实现源码分析


    【一】spring的远程调用提供的基础类

    (1)org.springframework.remoting.support.RemotingSupport

    ===>spring提供实现的远程调用客户端实现的基础类

    ===>例子:org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean

          org.springframework.remoting.caucho.HessianProxyFactoryBean

    (2)org.springframework.remoting.support.RemoteExporter

    ===>spring提供实现的远程调用服务端实现的基础类

    ===>例子:org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter

         org.springframework.remoting.caucho.HessianServiceExporter

    【二】spring的远程调用基于Http协议实现的封装,以该例子分析远程调用实现原理和源码分析

    (1)HttpInvokerProxyFactoryBean  客户端的实现

    ===>HttpInvokerProxyFactoryBean类是一个FactoryBean的实现接口,注入IOC后,未来向IOC申请bean,其实返回的是getObject()方法返回的实现.在实例化阶段会调用afterPropertiesSet() 进行初始化.根据配置创建代理对象.

    ===>在getObject()方法中,是完成了一个代理对象的封装.代理增强的配置:serviceUrl和serviceInterface.一个配置的请求url,一个配置的要代理的接口.

    ===>该代理对象的增强实现就是org.springframework.remoting.httpinvoker.HttpInvokerClientInterceptor的invoke(MethodInvocation methodInvocation) 方法.也就是HttpInvokerProxyFactoryBean的父类.将来会作为增强实现,加入到代理对象中.

    ===>未来发起调用.其实底层是代理对象的拦截器,也就是HttpInvokerClientInterceptor调用invoke方法.将数据类序列化,利用serviceUrl向远程调用接口发送http请求.

    (2)HttpInvokerServiceExporter  服务端的实现

    ===>HttpInvokerServiceExporter类是org.springframework.web.HttpRequestHandler的实现类.该类在实例化的时候,会调用afterPropertiesSet()初始化.如果配置有拦截器(即属性Object[] interceptors),则需要为实际调用的facadeImpl创建代理对象.

    ===>该类将来会作为一个bean加入到org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping中.

    ===>当客户端发送请求,进入DispatcherServlet中,从beanNameUrlHandlerMapping中获取该bean,再用该bean找到org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter.该HttpRequestHandlerAdapter会判断bean是否是HttpRequestHandler的实现类的实例.如果是,调用HttpInvokerServiceExporter类的handleRequest()方法去实现真正facadeImpl的调用

    ===>在配置HttpInvokerServiceExporter的时候的配置

      >需要配置url,将来作为和客户端的请求地址的匹配.

      >需要配置所代理的接口.

      >需要配置真正的实现类的实例,该实例也可能在实例化bean的时候如果有aop配置,其实也是一个代理对象.这就是多层代理.多层代理在技术层面是允许的.

    (3)BeanNameUrlHandlerMapping,HttpRequestHandlerAdapter是如何加载进IOC容器中的?

    ===>初始化DispatcherServlet的时候,最后会调用initStrategies(ApplicationContext context)方法,内部有初始化的方法,从配置文件里加载,然后编码方式加入IOC容器.从DispatcherServlet.properties文件中获取相应的配置.

    ===>BeanNameUrlHandlerMapping是ApplicationContextAware 接口的实现类.在IOC容器实例化阶段,会调用setApplicationContext(ApplicationContext context)进行映射配置.

    【三】以HttpInvoker为例子写一个服务端和客户端

    (1)facade接口

    package com.mobile.thinks.user.facade;
    
    import com.mobile.thinks.user.dto.UserDTO;
    /**
     * 接口
     * @author sxf
     *
     */
    public interface UserFacade {
        
        public  UserDTO updateUserByUserDTO(UserDTO userDTO);
    }
    View Code

    (2)facade接口的参数

    package com.mobile.thinks.user.dto;
    
    import java.io.Serializable;
    
    public class UserDTO implements Serializable {
    
        private String id;
        private String name;
        private String address;
        private int age;
        private String sex;
        public String getId() {
            return id;
        }
        public void setId(String id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getAddress() {
            return address;
        }
        public void setAddress(String address) {
            this.address = address;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        public String getSex() {
            return sex;
        }
        public void setSex(String sex) {
            this.sex = sex;
        }
        
    }
    View Code

    (3)facade实现

    package com.mobile.thinks.user.facade.impl;
    
    import org.springframework.stereotype.Component;
    
    import com.mobile.thinks.user.dto.UserDTO;
    import com.mobile.thinks.user.facade.UserFacade;
    
    @Component(value="userFacade")
    public class UserFacadeImpl implements UserFacade{
    
        @Override
        public UserDTO updateUserByUserDTO(UserDTO userDTO) {
            System.out.println("传过来的参数ID====>"+userDTO.getId());
            System.out.println("传过来的参数Name===>"+userDTO.getName());
            System.out.println("传过来的参数Address===>"+userDTO.getAddress());
            System.out.println("传过来的参数Age===>"+userDTO.getAge());
            System.out.println("传过来的参数Sex===>"+userDTO.getSex());
            
            UserDTO dto=new UserDTO();
            dto.setId("abcdefghijklmnopqrstuvwxyz");
            dto.setName("尚晓飞");
            dto.setSex("男");
            dto.setAge(28);
            dto.setAddress("三门峡");
            return dto;
        }
        
        
    
    }
    View Code

    (4)客户端配置实现

    <bean id="userFacade" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
                  <property name="serviceUrl"><value>http://localhost:8080/thinks-webservice/http/userFacade</value></property>
                  <property name="serviceInterface"><value>com.mobile.thinks.user.facade.UserFacade</value></property>
              </bean>
    View Code

    (5)服务端配置实现

     <bean name="/http/userFacade" class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">
            <property name="serviceInterface"><value>com.mobile.thinks.user.facade.UserFacade</value></property>
            <property name="service" ref="userFacade" />
        </bean>
    View Code
  • 相关阅读:
    猜数字小游戏的设计
    实验三 敏捷开发与XP实践 实验报告
    实验二Java面向对象程序设计
    课程总结报告
    Android实践项目汇报总结(下)
    Android实践项目汇报总结(上)修改
    Android项目开发四
    Android项目开发三
    Android项目开发二
    Android项目开发一
  • 原文地址:https://www.cnblogs.com/shangxiaofei/p/7284774.html
Copyright © 2020-2023  润新知