2013-02-13 2 views
0

Я пытаюсь разработать код полезности, который переносится как на платформы J2SE, так и на платформы Android для кэширования объектов. План состоит в том, чтобы извлечь абстрактный класс, когда я его работаю, но пока он является частью окончательной реализации класса.Интроспекция карты

Объект, который я хочу кэшировать, только что был создан и передан методу store(Object, Object), который станет частью абстрактного класса в окончательной версии, поэтому ему нужно использовать интроспекцию, чтобы определить, как хранить данные, которые были переданы.

Алгоритм не очень сложна:

1). Сканируйте методы объекта, которые ищут атрибут @Id, и если он найден, используйте его для извлечения ключа объекта.

2). Сканируйте собственный класс метода store() для поля, которое реализует метод put(key.getClass(), value.getClass()) и использует его для кэширования объекта.

Часть (1) работает нормально, это часть (2), что я не могу работать. Я получаю:

DEBUG c.n.v.ui.cache.Cache Not found: operativesMap.put(String, OperativeEntity) 
WARN c.n.v.ui.cache.Cache Object Joe Bloogs, with key cac57510-c9c6-11df-8000-b56f1ffcb182 not cached! 
INFO c.n.v.ui.cache.Cache Object Joe Bloggs, with key cac57510-c9c6-11df-8000-b56f1ffcb182 cached. 

авторизовались показывает, что код самоанализ не удалось найти метод пут и упал, хотя проверки логики двойной (которые должны будут быть удалены, когда я двигаюсь, что метод абстрактного класса).

Как всегда большое спасибо за помощь в этом.

Стив

public void store(Object key, 
      Object value) { 
    if (log.isInfoEnabled()) 
     log.info("Storing: " + key + " => " + value); 

    for (Field field: getClass().getDeclaredFields()) 
     if (store(field, key, value)) 
     return; 

    log.warn("Object " + value + ", with key " + key + " not cached!"); 

    if (value instanceof OperativeEntity) { 
     operativesMap.put(key.toString(), (OperativeEntity) value); 
     log.info("Object " + value + ", with key " + key + " cached."); 

     // How did I get here, and I do - the loop above should have found 
     // operativesMap, it's put method and stored the value 
    } 
} 

public boolean store(Field field, 
      Object key, 
      Object value) { 
    try { 
     Method method = field.getClass().getMethod("put", key.getClass(), value.getClass()); 

     if (null != method) 
      return store(field.get(this), method, key, value); 

     else 
      return false; 

    } catch (NoSuchMethodException cause) { 
     if (log.isDebugEnabled()) 
     log.debug("Not found: " + field.getName() + ".put(" + key.getClass().getSimpleName() 
        + ", " + value.getClass().getSimpleName() + ")"); 
     return false; 

    } catch (Exception cause) { 
     log.error("Stroing " + key + "=>" + value + " mapping", cause); 
     return false; 
    } 
} 

public boolean store(Object obj, 
      Method method, 
      Object key, 
      Object value) { 
    try { 
     method.invoke(obj, key, value); 
     if (log.isInfoEnabled()) 
      log.info(">>>>>> Cached " + key + "=>" + value); 
     return true; 

    } catch (Exception cause) { 
     log.error("Stroing " + key + "=>" + value + " mapping", cause); 
     return false; 
    } 
} 

Update:

Для тех, кто читает это в будущем, код для нахождения метода пут, который работает приведен ниже:

public boolean store(Field field, 
     Object key, 
     Object value) { 
try { 
    Object obj = field.get(this); 
    Method method = obj.getClass().getMethod("put", Object.class, Object.class); 

    if (null != method) { 
    Class[] params = method.getParameterTypes(); 
    if (log.isDebugEnabled()) 
     log.debug(" Found: put(" + params[0].getSimpleName() + ", " + params[1].getSimpleName() + ")"); 

    if (params[0].isAssignableFrom(key.getClass()) 
     && params[1].isAssignableFrom(value.getClass())) 
     return store(obj, method, key, value); 

    else 
     return false; 

    } else 
    return false; 

} catch (NoSuchMethodException cause) { 
    if (log.isDebugEnabled()) 
    log.debug("Not found: " + field.getName() + ".put(Object, Object)"); 
    return false; 

} catch (Exception cause) { 
    log.error("Storing " + key + "=>" + value + " mapping", cause); 
    return false; 
} 
} 

ответ

0

Class.getMethod() принимает фактические объявленные типы параметров. Таким образом, для карты это будет getMethod("put", Object.class, Object.class). Если вы просто хотите найти метод put(), который может принять тип ключа и значения, который у вас есть, вам нужно будет перебирать методы класса и проверять параметры с помощью Class.isAssignableFrom().

+0

Спасибо, Рассел, Не нужно было итерации через методы, я просто использовал 'getMethod (" put ", Object.class, Object.class)', а затем проверил параметры. Но в моем коде была ошибка, и я искал 'put (...)' в поле 'Field', а не на рассматриваемом объекте. – Dobbo

Смежные вопросы