Я пытаюсь разработать код полезности, который переносится как на платформы 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;
}
}
Спасибо, Рассел, Не нужно было итерации через методы, я просто использовал 'getMethod (" put ", Object.class, Object.class)', а затем проверил параметры. Но в моем коде была ошибка, и я искал 'put (...)' в поле 'Field', а не на рассматриваемом объекте. – Dobbo