Spring未使用AOP挑选更新的@Query值 [英] Spring not picking updated @Query value Using AOP

查看:0
本文介绍了Spring未使用AOP挑选更新的@Query值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

JPA:方法

@Repository
public interface FloorRepository extends JpaRepository<TnFloor, Integer> {
  @Query("select distinct tnFloor from TnFloor tnFloor where tnFloor.tnBuilding.buildingId in ?1")
  public List<TnFloor> findByBuildingIds(List<Integer> buildingIds);
}   
  @Before("dataRolesPointCuts()")
  public void beforeMethods(JoinPoint joinPoint) {

    log.debug(" Before Advice Called " + joinPoint.toShortString());
    String classArray[]=joinPoint.getTarget().getClass().getGenericInterfaces()[0].getTypeName().split("\.");
    String className = classArray[classArray.length-1];
    String methodName = joinPoint.getSignature().getName();
    String securedMethodName = className + "_" + methodName;
    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

    if(authentication!=null)
    {
      UserDetailsImpl userDetails = (UserDetailsImpl) authentication.getPrincipal();
      String loggedINUserName = userDetails.getUsername();
      Map<String, Map<String, String>> userRoleMap = usernameRoleMap.get(loggedINUserName);
      TnMethodSecurityModel methodSecurity = methodSecurityMap.get(securedMethodName); // Replace with Map

      if(methodSecurity!=null && methodSecurity.getTnMethodSecurityFilters()!=null && methodSecurity.getTnMethodSecurityFilters().size()>0)
      {
        Class<?> clazz =((Class<?>) joinPoint.getTarget().getClass().getGenericInterfaces()[0]);
        try {
          Method[] methods = clazz.getMethods();
          Method method=null;
          for(Method meth: methods )
          {
            if(meth.getName().equals(methodName))
            {
              method=meth;
              break;
            }
          }

          if(method == null)
            return;

          Query secParam = method.getAnnotation(Query.class);
          String query=secParam.value();
          String securityPredicate=Util.getSecuirtyPredicate(methodSecurity, userRoleMap);

          try {
            System.out.println("old MethodAnnotation = " + secParam.value());
            Util. changeAnnotationValue(secParam, "value", query+" "+securityPredicate);
            System.out.println("Asspect Query :: "+query);
          }   catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          }
          System.out.println("modified MethodAnnotation = " + secParam.value());

        } catch ( SecurityException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      }
    }

    log.info("Executing   with argument: {}", className + " " + methodName);
  }

  @SuppressWarnings("unchecked")
  public static Object changeAnnotationValue(Annotation annotation, String key, Object newValue){
    Object handler = Proxy.getInvocationHandler(annotation);
    Field f;
    try {
      f = handler.getClass().getDeclaredField("memberValues");
    } catch (NoSuchFieldException | SecurityException e) {
      throw new IllegalStateException(e);
    }
    f.setAccessible(true);
    Map<String, Object> memberValues;
    try {
      memberValues = (Map<String, Object>) f.get(handler);
    } catch (IllegalArgumentException | IllegalAccessException e) {
      throw new IllegalStateException(e);
    }
    Object oldValue = memberValues.get(key);
    if (oldValue == null || oldValue.getClass() != newValue.getClass()) {
      throw new IllegalArgumentException();
    }
    memberValues.put(key,newValue);
    return oldValue;
  }

建议执行前输出:

old MethodAnnotation = select distinct tnFloor from TnFloor tnFloor where tnFloor.tnBuilding.buildingId in ?1 
 
modified MethodAnnotation = select distinct tnFloor from TnFloor tnFloor where tnFloor.tnBuilding.buildingId in ?1   (tnFloor.tnBuilding.buildingId IN (0,1,6)) 

但最终JPA正在执行修改前的查询输出:

select tnbuilding0_.building_id as building1_17_0_, tnbuilding0_.description as descript2_17_0_, tnbuilding0_.name as name3_17_0_, tnbuilding0_.site_id as site_id4_17_0_, tnsite1_.site_id as site_id1_65_1_, tnsite1_.description as descript2_65_1_, tnsite1_.email as email3_65_1_, tnsite1_.name as name4_65_1_, tnsite1_.url as url5_65_1_ from tn_building tnbuilding0_ inner join tn_site tnsite1_ on tnbuilding0_.site_id=tnsite1_.site_id where tnbuilding0_.building_id=?

推荐答案

很抱歉给您上课,但是...注释值是常量。您无法更改它们。您尝试更改它们在内存中的表示形式的老套方法可能是一种巧妙的练习,但糟糕的设计。如果您的应用程序或方面确实依赖于这样的东西,作为开发人员,您应该立即感受到重构的冲动。

至于为什么它不能像您想象的那样工作:您可能会认为,在执行带注释的方法之前,Spring每次都会读取注释。但通常这样的框架会在连接应用程序时扫描注释。

简单地说,对于您可能希望通过使用AOP或其他方式使其更具动态化的东西,不要使用硬编码常量(如在注释中)。如果您确实希望保留查询注释,但使用AOP,我认为您应该尝试挂钩到另一个组件,在该组件中,查询正在被解析或发送到数据库,并在那里进行修改。

这篇关于Spring未使用AOP挑选更新的@Query值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆