【一】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