【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);
}
(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;
} }
(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;
} }
(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>
(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>
【spring源码学习】spring的远程调用实现源码分析的更多相关文章
- Java并发包源码学习系列:线程池ScheduledThreadPoolExecutor源码解析
目录 ScheduledThreadPoolExecutor概述 类图结构 ScheduledExecutorService ScheduledFutureTask FutureTask schedu ...
- spring源码学习——spring整体架构和设计理念
Spring是在Rod Johnson的<Expert One-On-One J2EE Development and Design >的基础上衍生而来的.主要目的是通过使用基本的java ...
- spring cloud eureka + feign,api远程调用
网上教程不少,有些就是复制粘贴,不结合实际生产. eureka不再阐述. 一般正常开发会有多个工程,且多个module. 我的习惯是: eureka server.权限.config.gateway ...
- Spring系列:学习Spring的资源和讨论
1) 阅读<spring in action 4th edition>,这样可以对的spring可以做什么事情有个基本了解: 2) 阅读spring.io官网提供的各种reference, ...
- Java并发包源码学习系列:线程池ThreadPoolExecutor源码解析
目录 ThreadPoolExecutor概述 线程池解决的优点 线程池处理流程 创建线程池 重要常量及字段 线程池的五种状态及转换 ThreadPoolExecutor构造参数及参数意义 Work类 ...
- Java并发包源码学习系列:同步组件CountDownLatch源码解析
目录 CountDownLatch概述 使用案例与基本思路 类图与基本结构 void await() boolean await(long timeout, TimeUnit unit) void c ...
- Java并发包源码学习系列:同步组件CyclicBarrier源码解析
目录 CyclicBarrier概述 案例学习 类图结构及重要字段 内部类Generation及相关方法 void reset() void breakBarrier() void nextGener ...
- Java并发包源码学习系列:同步组件Semaphore源码解析
目录 Semaphore概述及案例学习 类图结构及重要字段 void acquire() 非公平 公平策略 void acquire(int permits) void acquireUninterr ...
- Qt Creator 源码学习笔记04,多插件实现原理分析
阅读本文大概需要 8 分钟 插件听上去很高大上,实际上就是一个个动态库,动态库在不同平台下后缀名不一样,比如在 Windows下以.dll结尾,Linux 下以.so结尾 开发插件其实就是开发一个动态 ...
随机推荐
- Java:判断字符串是否为数字的五种方法
Java:判断字符串是否为数字的五种方法 //方法一:用JAVA自带的函数 public static boolean isNumeric(String str){ for (int i = str. ...
- mysql全库搜索指定字符串
mysql全库搜索指定字符串 DELIMITER // DROP PROCEDURE IF EXISTS `proc_FindStrInAllDataBase`; # CALL `proc_FindS ...
- Memcached add 命令
Memcached add 命令用于将 value(数据值) 存储在指定的 key(键) 中. 如果 add 的 key 已经存在,则不会更新数据,之前的值将仍然保持相同,并且您将获得响应 NOT_S ...
- JavaScript tips —— target与currentTarget的区别
定义 以下是红宝书的描述 属性/方法 类型 读/写 说明 currentTarget Element 只读 其事件处理程序当前正在处理事件的那个元素 target Element 只读 事件的目标 M ...
- js关闭浏览器窗口及检查浏览器关闭事件
js关闭浏览器窗口,不弹出提示框.支持ie6+,火狐,谷歌等浏览器,下面以一个示例为大家详细介绍下具体的实现方法,感兴趣的朋友可以参考下 js关闭浏览器窗口 js关闭浏览器窗口,不弹出提示框.支持 ...
- python random使用生成随机字符串
应用python random标准库做一个随机生成密码的程序,可以随机生成任意多个字符.(基于python2.7,如果是python3需要修改下) 案例: #-*-coding:utf-8 -*-#a ...
- python函数语法学习
Python函数 定义函数 在Python中,定义一个函数用def语句,一次写出函数名.括号中的参数和冒号:,函数返回使用return语句. def myDef(x): if x >= 0: r ...
- Codeforces Round #181 (Div. 2)C
用lucas定理, p必须是素数 对于单独的C(n, m) mod p,已知C(n, m) mod p = n!/(m!(n - m)!) mod p.显然除法取模,这里要用到m!(n-m)!的逆元. ...
- Mysql的锁机制——待写
发酵独守空房飞杀戮空间爱的色放
- day5-time & datetime模块
1.概述 程序设计开发过程中,往往存在很多场景,需要把时间和日期以某种特定形式格式化输出,在python中我们需要借助time & datetime模块来实现,今天就来一探这两大模块的究竟. ...