TCP-IP学习笔记九:通过Spring打造通用RPC架构webService
标签(空格分隔): RPC-IP
在前几篇的学习中我们得到了一个简单的RPC机构的webService程序。在学习Spring的过程中,想到可以用过Spring对我们的程序进行扩展我们利用Spring提供的接口进行扩展,是的我们的程序更具有通用性。
Spring可以通过配置文件进行扩展的注入Bean,同时也可以通过java代码进行注入Bean。Spring为我们提供了BeanFactoryPostProcessor接口,Spring在加载的时候就会加载这个接口的实现类中的postProcessBeanFactory方法,达到注入Bean的效果。(了解Spring注入Bean的过程的同学应该很快想到是怎么样的过程,Spring在读取配置文件xml之后,对xml文件进行解析,进而加载到BeanDefinition对象中,然后加载到容器中。。。)这个过程类似Spring提供的扫描的功能。
知道这个特性之后我们可以通过这个接口在Spring工厂加载的时候将我们的代理类加载到容器中,同时通过配置文件将我们的接口注入到容器中。
下面就在代码中解释我们的程序升级:
新建一个类BeanScanner实现BeanFactoryPostProcessor接口
package com.motui.rpc.client;
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 java.util.Map;
/**
* Created by MOTUI on 2016/10/20.
*/
public class BeanScanner implements BeanFactoryPostProcessor {
//key是Bean的名称,value是具体的接口全限定名
private Map<String,Class> beanInterfaces;
//客户端名称
private String clientName;
//提供set方法,使用set注入。同时也可以通过构造注入,自行扩展。
public void setBeanInterfaces(Map<String, Class> beanInterfaces) {
this.beanInterfaces = beanInterfaces;
}
public void setClientName(String clientName) {
this.clientName = clientName;
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
//DefaultListableBeanFactory,spring默认的IoC容器
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) configurableListableBeanFactory;
//遍历Map构造BeanDefinition
for (Map.Entry<String,Class> entity: beanInterfaces.entrySet()) {
String beanName = entity.getKey();
Class targetInterface = entity.getValue();
//和<bean class="com.motui.rpc.client.FactoryBeanProxy">同理
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(com.motui.rpc.client.FactoryBeanProxy.class);
//【特别注意】以下的注入方式是根据FactoryBeanProxy类的参数注入类型决定
// <constructor-arg index="0" value="com.motui.service.IUserService"/>同理
beanDefinitionBuilder.addConstructorArgValue(targetInterface);
//<property name="client" ref="client"/>同理
beanDefinitionBuilder.addPropertyReference("client",clientName);
//获得BeanDefinition
AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
//注册BeanDefin
beanFactory.registerBeanDefinition(beanName,beanDefinition);
}
}
}
客户端配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd">
<!-- 配置代理bean -->
<bean class="com.motui.rpc.client.BeanScanner">
<property name="beanInterfaces">
<map>
<entry key="authentication" value="com.motui.IAuthentication"/>
.....
.....
</map>
</property>
<property name="clientName" value="client"/>
</bean>
<bean id="client" class="com.motui.rpc.client.RemoteRPCClient">
<constructor-arg index="0" value="192.168.1.110"/>
<constructor-arg index="1" value="8989"/>
</bean>
</beans>
总结:
在学习Spring源码过程中渐渐体会到Spring的强大之处,也感受到了开源的魅力。在接下来的日子中会分享对Spring源码的分析和理解。也建议大家多看源码,体会大神们开发的经验和思想。