动态执行bean对象的方法

时间:2018-08-18 04:47:19

标签: spring spring-boot spring-aop spring-restcontroller spring-rest

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

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

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

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

Ex:

    processEmployee(EmployeeRequest request)

    procesStudent(StudentRequest request)

我一直在寻找一种方法来动态改变 自己在同一对象字段上的数据(例如:EmployeeRequest,StudentRequest)

我尝试并遵循的第四步是以下方法。

1。引入了新的注释。

2。注释那些具有加密数据的字段。

3。检索所有带注释的字段。

4。每个字段数据我们将应用解密逻辑并  解密后的数据将再次注入同一字段

我正在寻找实现第四步的api吗?

是否有任何可用于动态执行的api 同一对象上的方法 或任何参考,请指出我。

1 个答案:

答案 0 :(得分:2)

我的建议是不要对加密/解密的类都使用相同的POJO。它使将来的使用变得混乱(就像我收到了EmployeeRequest实例一样,是否已解密?),并且还限制了类型(因为您的加密/解密数据必须是同一类型)。

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

  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之间的映射以提高性能。