把大象放进冰箱--spring自动扫描并发布rmi
博客专区 > Mr_Qi 的博客 > 博客详情
把大象放进冰箱--spring自动扫描并发布rmi
Mr_Qi 发表于1年前
把大象放进冰箱--spring自动扫描并发布rmi
  • 发表于 1年前
  • 阅读 82
  • 收藏 3
  • 点赞 0
  • 评论 0

腾讯云 技术升级10大核心产品年终让利>>>   

对于需要暴露大量rmi的应用来说,每次新增加一个service都需要手写一段xml也是蛮累的……

偷懒的程序员想到了如下的办法

利用component-scan发布service同时发布rmi呢?

说做就做

把大象放进冰箱三步骤

  1. 打开冰箱门
    首先需要把所有的@service注解扫描,设置BeanDefinition的相关属性包括service,serviceName等
  2. 把大象塞进冰箱
    将BeanDefinition注册到spring容器中
  3. 关上冰箱门
    初始化对应的BeanDefinition


    具体代码如下

    /**
     * Created by qixiaobo on 2016/10/8.
     */
    public class PublishRmiBean implements ApplicationContextAware {
        private Logger logger = Logger.getLogger(PublishRmiBean.class);
        private String basePkg;
        private ApplicationContext context;
        private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
        @Value("${erp.rmi.base.port}")
        private int port;
     
        private MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(this.resourcePatternResolver);
     
        private static final List<TypeFilter> includeFilters = new LinkedList<>();
        private static final String DEFAULT_RESOURCE_PATTERN = "**/*.class";
     
     
        public String getBasePkg() {
            return basePkg;
        }
     
        public void setBasePkg(String basePkg) {
            this.basePkg = basePkg;
        }
     
        static {
            includeFilters.add(new AnnotationTypeFilter(Service.class));
        }
     
        @PostConstruct
        public void init() throws IOException {
            assert (basePkg != null);
            String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
                    resolveBasePackage(basePkg) + "/" + DEFAULT_RESOURCE_PATTERN;
            Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath);
            for (Resource resource : resources) {
                {
                    try {
                        MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);
                        if (isCandidateComponent(metadataReader)) {
                            ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
                            sbd.setResource(resource);
                            sbd.setSource(resource);
                            if (isCandidateComponent(sbd)) {
                                String clazzName = sbd.getBeanClassName();
                                Class clazz = null;
                                if (sbd.hasBeanClass()) {
                                    clazz = sbd.getBeanClass();
                                } else {
                                    clazz = Class.forName(clazzName);
                                }
                                String beanName = RmiNameGenerator.getBeanName(clazzName.substring(clazzName.lastIndexOf(".") + 1));
                                registerRmi(clazz, beanName);
                            }
                        }
                    } catch (Throwable e) {
                        logger.error(e);
                    }
                }
            }
            try {
                context.getBeansOfType(RmiServiceExporter.class);
            } catch (Exception ex) {
                logger.error(ex);
            }
     
        }
     
        private void registerRmi(Class clazz, String beanName) {
            BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(RmiServiceExporter.class);
            if (clazz.getInterfaces().length == 0) {
                logger.warn("skip publish rmi:" + beanName + " because no interface found!");
                return;
            }
            builder.addPropertyValue("serviceInterface", clazz.getInterfaces()[0]);
            builder.addPropertyValue("serviceName", beanName);
            builder.addPropertyValue("registryPort", port);
            builder.addPropertyReference("remoteInvocationExecutor", "clientInfoRemoteInvocationExecutor");
            builder.addPropertyValue("service", context.getBean(clazz));
            builder.setLazyInit(false);
            getBeanDefinitionRegistry().registerBeanDefinition(beanName + "Exporter", builder.getRawBeanDefinition());
            logger.info("publish rmi:" + beanName);
        }
     
     
        private BeanDefinitionRegistry getBeanDefinitionRegistry() {
            return (BeanDefinitionRegistry) ((XmlWebApplicationContext) context).getBeanFactory();
        }
     
        private boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
            for (TypeFilter tf : includeFilters) {
                if (tf.match(metadataReader, this.metadataReaderFactory)) {
                    return true;
                }
            }
            return false;
        }
     
        private boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
            return (beanDefinition.getMetadata().isConcrete() && beanDefinition.getMetadata().isIndependent());
        }
     
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            this.context = applicationContext;
        }
     
        private String resolveBasePackage(String basePackage) {
            return ClassUtils.convertClassNameToResourcePath(basePackage);
        }
     
    }

    在spring的xml中注册如下

    <bean class="com.xxx.PublishRmiBean" >
        <property name="basePkg" value="com.xxx.service.*.impl"/>
    </bean>

     

标签: Spring rmi
共有 人打赏支持
粉丝 193
博文 201
码字总数 212189
×
Mr_Qi
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: