2010-01-13 5 views
2

je une application qui utilise ehcache pour le cache (mais je pense que ce problème est le cadre agnostique), avec un intercepteur de méthode donc en gros si je marque ma méthode pour la mise en cache quelque chose comme ceci happnes:problème d'intégrité du cache

public Object invoke(MethodInvocation mi) throws Throwable { 
     Object result = cache.get(key); 
     //key comes from MethodInvocation processing 
     if (result == null) { 
      result = mi.proceed(); 
      cache.put(key, result); 
     } 
     return result; 
} 

Jusqu'ici tout va bien. La chose que je suis en cache une méthode qui retourne un Array, et est appelé comme ceci:

List<Object> result = methodWithCaching(); 
result.add(new Object()); //! 

Comme vous pouvez l'imaginer, la ligne marquée ! met également à jour l'instance de cache, et ce n'est pas ce que je veux.

Quelqu'un peut-il penser à un moyen d'arrêter ce comportement sans modifier le client, seul l'intercepteur?

Répondre

0

Que voulez-vous dire par "mise à jour du cache"? Êtes-vous concerné que les utilisateurs peuvent modifier la liste retournée par methodWithCaching()? Si oui, je proposerais que cette méthode renvoie une collection non modifiable. Ou peut-être que le cache peut détecter que le résultat est une collection et l'envelopper avec un wrapper non modifiable.

+0

Je veux que les utilisateurs fassent ce qu'ils veulent avec la liste. Mais imaginez ce scénario: methodinvocation (1), cache miss, userupdates les listes et le cache est mis à jour aussi. methodinvocation (2), cache hit (maintenant la liste contient 1 élément), l'utilisateur met à jour la liste et le cache est mis à jour aussi. methodinvocation (3), cache hit (maintenant la liste contient 2 éléments), et ainsi de suite. –

+0

Voulez-vous que l'utilisateur dispose d'une copie locale de l'objet mis en cache et non d'une instance partagée? – Kevin

+0

C'est vrai, et probablement sans modifier le client, juste l'intercepteur –

0

Ma compréhension est que vous voulez que l'intercepteur renvoie une copie du résultat mis en cache, afin que les modifications du client n'affectent que la copie?

Je ne peux pas penser à un bon moyen et général pour le faire si pour être honnête. Laids seraient de compter sur clone(), ou de créer une nouvelle liste à chaque fois.

Il semble que vous devriez vraiment modifier le client à la place, si possible.

+0

La chose est que je ne peux pas créer un nouvel objet. Je ne peux certainement pas appeler 'clone' car c'est une méthode protégée. Et aussi la valeur de retour peut être n'importe quoi, pas seulement des listes. –

+0

Comme je l'ai dit, il n'y a pas de bonne solution. 'clone()' est cassé par la conception; vous devez faire 'if (result instanceof Cloneable)' puis invoquer 'clone()' via la réflexion. –