通过自定义reflector实现对mybatis实体类带有自定义注解的属性进行加解密

自定义 Reflector 实现可以通过扩展 MyBatis 的 Reflector 实现类来实现对实体类带有自定义注解的属性进行加解密处理。

自定义组件
注解

首先需要定义一个自定义注解,用于标记需要进行加密和解密处理的实体类属性。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface EncryptColumn {
}
加解密接口
public interface ColumnEncryptor {

    Object encrypt(Object object);

    Object decrypt(Object object);

}
实现Reflector

接下来创建一个自定义 Reflector 类,继承 MyBatis 的 Reflector 实现类,并覆盖其 getSetInvoker、getGetInvoker方法,实现对带有 EncryptColumn 注解的属性进行加解密处理。

public class EncryptReflector extends Reflector {

    private final Map<String, Field> fieldMap;

    private final ColumnEncryptor encryptor;

    public EncryptReflector(Class<?> type, ColumnEncryptor encryptor) {
        super(type);
        this.encryptor = encryptor;
        this.fieldMap = new HashMap<>();
        for (Field field : type.getDeclaredFields()) {
            fieldMap.put(field.getName(), field);
        }
    }

    @Override
    public Invoker getSetInvoker(String propertyName) {
        log.info("propertyName={}", propertyName);
        Invoker invoker = super.getSetInvoker(propertyName);
        EncryptColumn encryptColumn = this.getEncryptColumn(propertyName);
        if (encryptColumn == null) {
            return invoker;
        }
        return new Invoker() {
            @Override
            public Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException {
                Object[] decryptArgs = Arrays.stream(args).map(EncryptReflector.this.encryptor::decrypt).toArray();
                log.info("property={}, args={}, decryptArgs={}", propertyName, args, decryptArgs);
                return invoker.invoke(target, decryptArgs);
            }

            @Override
            public Class<?> getType() {
                return invoker.getType();
            }
        };
    }

    @Override
    public Invoker getGetInvoker(String propertyName) {
        Invoker invoker = super.getGetInvoker(propertyName);
        EncryptColumn encryptColumn = this.getEncryptColumn(propertyName);
        if (encryptColumn == null) {
            return invoker;
        }
        return new Invoker() {
            @Override
            public Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException {
                Object origin = invoker.invoke(target, args);
                Object encrypt = EncryptReflector.this.encryptor.encrypt(origin);
                return encrypt;
            }
            @Override
            public Class<?> getType() {
                return invoker.getType();
            }
        };
    }

    private EncryptColumn getEncryptColumn(String propertyName) {
        Field field = this.fieldMap.get(propertyName);
        if (field == null) {
            return null;
        }
        return field.getAnnotation(EncryptColumn.class);
    }

}

在上述代码中,覆盖了 Reflector 类的getSetInvoker、getGetInvoker方法,当找到带有 EncryptColumn注解的属性时,通过加密和解密函数对属性进行处理,返回加密或解密后的值。

注册Reflector
自定义ConfigurationCustomizer

最后通过实现 ConfigurationCustomizer 的替换 Configuration 中原有的 reflectorFactory(默认采用的DefaultReflectorFactory)。

public class ReflectorConfigurationCustomizer implements ConfigurationCustomizer {

    private ColumnEncryptor encryptor;

    public ReflectorConfigurationCustomizer(ColumnEncryptor encryptor) {
        this.encryptor = encryptor;
    }

    @Override
    public void customize(Configuration configuration) {
        configuration.setReflectorFactory(new EncryptReflectorFactory(this.encryptor));
    }

}
实现ReflectorFactory类

其中 EncryptReflectorFactory 是自定义的 Reflector 工厂类,其实现如下:

public class EncryptReflectorFactory implements ReflectorFactory {

    private boolean classCacheEnabled = true;

    private final ColumnEncryptor encryptor;

    private final ConcurrentMap<Class<?>, Reflector> reflectorMap;

    public EncryptReflectorFactory(ColumnEncryptor encryptor) {
        this.encryptor = encryptor;
        this.reflectorMap = new ConcurrentHashMap<>();
    }

    @Override
    public boolean isClassCacheEnabled() {
        return classCacheEnabled;
    }

    @Override
    public void setClassCacheEnabled(boolean classCacheEnabled) {
        this.classCacheEnabled = classCacheEnabled;
    }

    @Override
    public Reflector findForClass(final Class<?> type) {
        if (classCacheEnabled) {
            return reflectorMap.computeIfAbsent(type, t -> new EncryptReflector(type, this.encryptor));
        } else {
            return new EncryptReflector(type, this.encryptor);
        }
    }
}

在上述代码中,通过 ConcurrentHashMap 缓存 Reflector 实例,避免多次创建 Reflector 对象。

编写Configuration类
@Configuration
@ConditionalOnBean(ColumnEncryptor.class)
public class EncryptConfiguration {

    public EncryptConfiguration() {
        log.info("start encrypt");
    }

    @Bean
    public ConfigurationCustomizer reflectorConfigurationCustomizer(ColumnEncryptor encryptor) {
        return new ReflectorConfigurationCustomizer(encryptor);
    }

}

通过以上步骤,就可以实现对 MyBatis 实体类带有自定义注解的属性进行加解密处理。

使用方法

使用时需要根据自身业务需求实现ColumnEncryptor,并注册到spring容器

@Component
public class SimpleColumnEncryptor implements ColumnEncryptor {
    
    @Override
    public Object encrypt(Object object) {
        return object;
    }

    @Override
    public Object decrypt(Object object) {
        return object;
    }
    
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值