zoukankan      html  css  js  c++  java
  • 在spring容器中对中间件bean进行替换

    在应用中,当我们进行集成测试或者单元测试的时候,有些中间件因为涉及到了外部请求,所以想把测试拉起来,显得比较困难,但是由于spring中,我们可以对bean进行替换,所以这个事儿变得简单了。

    我们需要基于BeanDefinitionRegistryPostProcessor 和 PriorityOrdered两个类,来对bean进行处理:

    package org.tiny.upgrade.plugin.mock.mockbiz.mockbiz;//package com.jd.migration.service.replace;
    
    import com.alibaba.fastjson.JSON;
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.config.BeanDefinition;
    import org.springframework.beans.factory.config.ConfigurableBeanFactory;
    import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
    import org.springframework.beans.factory.support.BeanDefinitionBuilder;
    import org.springframework.beans.factory.support.BeanDefinitionRegistry;
    import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
    import org.springframework.beans.factory.support.RootBeanDefinition;
    import org.springframework.core.Ordered;
    import org.springframework.core.PriorityOrdered;
    import org.springframework.stereotype.Component;
    
    //@Component
    public class BeanReplace implements BeanDefinitionRegistryPostProcessor, PriorityOrdered {
    
        @Override
        public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
           System.out.println(JSON.toJSONString("xxxx"+beanDefinitionRegistry));
            for (String beanDefinitionName : beanDefinitionRegistry.getBeanDefinitionNames()) {
                String beanName = "redisClient";
                if(beanDefinitionName.equals(beanName)){
                    //移除原有bean
                    beanDefinitionRegistry.removeBeanDefinition(beanName);
                    System.out.println("注册新的mock beanName:"+beanName);
                    RootBeanDefinition beanDefinition = (RootBeanDefinition) BeanDefinitionBuilder.rootBeanDefinition(BeanFactory.class)
                            .setFactoryMethod("mock")
                            .addConstructorArgValue(loadClass("org.tiny.cli.Cluster", beanDefinitionRegistry))
                            .setLazyInit(false)
                            .setScope(BeanDefinition.SCOPE_SINGLETON)
                            .getBeanDefinition();
                    beanDefinition.setTargetType(loadClass("org.tiny.cli.Cluster", beanDefinitionRegistry));
                    //注入mock的bean
                    beanDefinitionRegistry.registerBeanDefinition(beanName, beanDefinition);
                }
            }
        }
    
        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
    
        }
    
        @Override
        public int getOrder() {
            return Ordered.LOWEST_PRECEDENCE - 10000;
        }
    
    
        public Class loadClass(String className, BeanDefinitionRegistry beanDefinitionRegistry) throws RuntimeException {
            ConfigurableBeanFactory cbf = (ConfigurableBeanFactory) beanDefinitionRegistry;
            Class clazz = tryLoadClass(cbf.getBeanClassLoader(), className);
            if (clazz != null) {
                return clazz;
            }
            return tryLoadClass(cbf.getTempClassLoader(), className);
        }
    
        private Class tryLoadClass(ClassLoader classLoader, String interfaceClassName) {
            try {
                return classLoader.loadClass(interfaceClassName);
            } catch (ClassNotFoundException e) {
                // 忽略
            }
            return null;
        }
    }

    从上面流程中,我们可以看到,我们先是移除了已经注册好的bean,之后创建了一个新的mock bean,并注册到spring的bean容器中。

    由于这里面,我们用到了工厂方法:.setFactoryMethod("mock"), 所以我们需要定义一个工厂类:

    public class BeanFactory {
    
        public static <T> T mock(Class<T> clazz) {
            System.out.println("创建mock的clazz:" + clazz.getName());
            return Mockito.mock(clazz);
        }
    
    
        public static Object original(Object obj) {
            System.out.println("创建mock的对象:" + obj.getClass().getName());
            return obj;
        }
    
    }

    跑起项目,可以看到bean被替换了。

  • 相关阅读:
    Django之ORM单表操作(增删改查)
    django之ORM数据库操作
    Django框架之模板继承和静态文件配置
    Django框架之第三篇模板语法
    Django框架之第二篇
    Django框架第一篇基础
    cookie和session
    自定义Web框架
    HTTP协议详细介绍
    数据库之多表查询
  • 原文地址:https://www.cnblogs.com/scy251147/p/15425362.html
Copyright © 2011-2022 走看看