动态执行bean对象的方法

Dynamic execution of the methods of bean object

目前我有一个要求我们的后端 spring rest api 将接收加密 json 格式的数据(很少有字段是加密的,很少有字段是纯文本) 然后应用解密,然后对数据应用一些业务逻辑,最后将数据存储到数据库中。

此解密逻辑正在重复多个服务实现方法。 所以我们决定将解密逻辑与实际业务逻辑隔离。

我正在使用 spring aop 解密数据,解密后 我传递给服务层方法的对象。

但是我的服务层方法包含不同类型的对象作为参数

例如:

    processEmployee(EmployeeRequest request)

    procesStudent(StudentRequest request)

我正在寻找一种方法如何动态更改 同一对象字段上的数据本身(例如:EmployeeRequest、StudentRequest)

我尝试了以下方法并坚持执行第 4 步。

1.Introduced 一个新注释。

2.Annotate 那些具有加密数据的字段。

3.Retrieve 所有带注释的字段。

4.Each 字段数据我们将应用解密逻辑和 解密后的数据将再次注入同一字段

我在寻找 api 来实现第 4 步?

有没有api可以动态执行 同一对象上的方法 或任何参考请指出我。

我的建议是不要对加密/解密使用相同的 POJO class。它让以后的使用变得混乱(好像我收到了一个 EmployeeRequest 实例,它是否被解密?),并且还限制了类型(因为你的 encrypted/decrypted 数据必须是相同的类型)。

现在,对于实施,您有两个选择:

  1. 使用显式 ConversionService

注册转换器:

@Component
public class EmployeeRequestConverter implements Converter<EmployeeRequest, EmployeeRequest> {

     @Override
     public EmployeeRequest convert(EmployeeRequest source) {
           // Apply your decryption logic
     }
}

为其他请求对象制作类似的转换器。

现在在您的控制器中:

public class MyController {

    private ConversionService conversionService;

    private MyService myService;

    @RequestMapping(...)
    public void aRequest(@RequestBody EmployeeRequest request) {
        myService.execute(conversionService.convert(request, EmployeeRequest.class));
    }

}
  1. 使用反射。

前提条件:您在加密字段上有 @Encrypted 注释。

与第一个解决方案不同,您不需要为每种类型的请求创建显式转换器。

@Service
public class DecryptionService {

     public void <T> T decrypt(T input) {
          Field[] fields = input.getClass().getDeclaredFields();
          for (Field field : fields) {
               Encrypted encrypted = field.getAnnotation(Encrypted.class);
               if (encrypted != null) {
                   try{
                      field.setAccessible(true);
                      Object val = field.get(input);
                      // Base on @Encrypted annotation in your val, do the decryption
                      Object decryptedVal = ...;
                      field.set(input, decryptedVal);
                   } catch (Exception ex) {
                   }
               }
          }
     }
}

现在您可以为您的控制器申请此服务了。

您可能想要缓存 Class.getDeclaredFields()Class<?> -> @Encrypted fields 之间的映射以提高性能。