解决完这个小问题,我总结了一份工作装X指南

前言

在最近开发财务系统的时候,遇到一个问题:因为集团财务数据库的权限控制,导致测试和预发布环境只有部分机器有访问集团财务数据库的权限,而代码中又不区分机器,导致开发测试过程中因为没有环境导致验证相关功能阻塞.本着不侵入业务代码的原则,尝试依赖spring去解决在特定环境下直接跳过访问集团财务数据库的方式来解决该问题.
既然要依赖spring来解决,那么就需要先了解下spring bean和mybatis自动注入的一些基本机制,顺便也为了以后写类似的装X代码做点准备.

1.spring-bean的生命周期

在这里插入图片描述

2.mybaitis注解自动扫描注入

在这里插入图片描述

目标方案

  1. 使用代理类替换mybatis自动生成的类
  2. 不影响spring本身的加载机制
  3. 可根据环境配置进行生效

实现方案

增加标记注解,用于标记可被代理的mapper类

@Retention(RetentionPolicy.RUNTIME)
public @interface MapperMock {
}

实现BeanPostProcessor,当存在环境变量为mapperMock=true时,用自己的代理类替换掉mapper自动生成的代理类

@ConditionalOnProperty(name = "mapperMock", havingValue = "true")
public class MapperMockBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof MapperFactoryBean) {
            MapperFactoryBean mapperFactoryBean = (MapperFactoryBean) bean;
            Class clazz = mapperFactoryBean.getMapperInterface();
            MapperMock mock = (MapperMock) clazz.getAnnotation(MapperMock.class);
            Class[] superClasses = clazz.getInterfaces();
            Class[] finalClasses = new Class[superClasses.length + 1];
            System.arraycopy(superClasses, 0, finalClasses, 1, superClasses.length);
            finalClasses[0] = clazz;
            if (mock == null) {
                return bean;
            } else {
                bean = new FactoryBean() {
                    @Override
                    public Object getObject() throws Exception {
                        return Proxy.newProxyInstance(clazz.getClassLoader(), finalClasses, new InvocationHandler() {
                            @Override
                            public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
                                Class returnType = method.getReturnType();
                                if (int.class.equals(returnType)) {
                                    return 0;
                                }
                                if (byte.class.equals(returnType)) {
                                    return 0;
                                }
                                if (float.class.equals(returnType)) {
                                    return 0f;
                                }
                                if (long.class.equals(returnType)) {
                                    return 0l;
                                }
                                if (double.class.equals(returnType)) {
                                    return 0d;
                                }
                                if (char.class.equals(returnType)) {
                                    return 0;
                                }
                                if (boolean.class.equals(returnType)) {
                                    return false;
                                }
                                if (short.class.equals(returnType)) {
                                    return 0;
                                }
                                return null;
                            }
                        });
                    }

                    @Override
                    public Class getObjectType() {
                        return clazz;
                    }

                    @Override
                    public boolean isSingleton() {
                        return true;
                    }
                };
            }
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

发散:简单装X指南
如果想依赖spring写一个通用代码框架
1.通过实现ImportBeanDefinitionRegistrar扫描特定注解
2.通过实现FactoryBean来定制需要生成的对象
3.通过实现BeanPostProcessor来对bean做特殊处理

例如可以写代码简化类似kqueue的配置工作~

范世龙

看到这里的小伙伴,如果你喜欢这篇文章的话,别忘了转发、收藏、留言互动!

如果对文章有任何问题,欢迎在留言区和我交流~

最近我新整理了一些Java资料,包含面经分享、模拟试题、和视频干货,如果你需要的话,欢迎私信我!

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值