TCP-IP学习笔记九:通过Spring打造通用RPC架构webService

8 篇文章 0 订阅
4 篇文章 0 订阅

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源码的分析和理解。也建议大家多看源码,体会大神们开发的经验和思想。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值