Y a-t-il un moyen d'insérer automatiquement du code dans une méthode?
J'ai le champ typique suivant avec un getter et un setter et je voudrais insérer le code indiqué dans la méthode du setter qui enregistre si le champ a été modifié comme étant modifié le champ. Eh bien, pour insérer le champ "IsfirstNtnamÉdifié" indiqué pour suivre également si le champ a été modifié ou non. p> Je ne sais pas non plus si je peux le sous-ensemble du nom de la méthode En tant que chaîne de l'intérieur de la méthode elle-même comme indiqué sur la ligne où j'ajoute le nom de champ comme une chaîne dans l'ensemble des champs mis à jour: Il semble que la réponse la plus évidente soit d'utiliser des modèles de code à l'intérieur de l'éclipse, mais je m'inquiète de devoir retourner le code plus tard. P> J'aurais dû utiliser ce code plus simple au lieu de l'exemple ci-dessus. Tout ce qu'il fait est d'ajouter le nom du champ comme une chaîne à un ensemble. Strong> p> } p> p> p> P> mise à jour des champs.Ajoud ("FirstName"); code>. Et je ne sais pas comment insérer des champs dans une classe où j'ajoute que j'ajoute le champ booléen qui suit si le champ a été modifié ou non auparavant (pour que l'efficacité puisse empêcher de manipuler le jeu):
Boolean Isfirstnamérified = Faux; code> p>
EDIT ::::::::::: H2>
3 Réponses :
Vous pouvez utiliser Classes de proxy dynamiques et Obtenez l'événement avant l'appel de SetFirstName code> et d'autres méthodes
SET ... code>, déterminez le nom du champ avec
méthode.Substring (3) code> => " Prénom ", et mettez-le dans
setfirstName code>. P>
Oui, vous pouvez, une approche consiste à utiliser une forme de manipulation de code octet (par exemple, Javassist , ASM , BCEL) ou une bibliothèque AOP de niveau supérieur assis sur le dessus d'un de ces outils, par exemple AspectJ , JBoss AOP.
Remarque: la plupart des bibliothèques JDO font cela pour la manipulation de la persistance. p>
Voici un exemple utilisant Javassist: P>
public class Person { private String firstName; public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } } public static void rewritePersonClass() throws NotFoundException, CannotCompileException { ClassPool pool = ClassPool.getDefault(); CtClass ctPerson = pool.get("Person"); CtClass ctSet = pool.get("java.util.LinkedHashSet"); CtField setField = new CtField(ctSet, "updatedFields", ctPerson); ctPerson.addField(setField, "new java.util.LinkedHashSet();"); CtMethod method = ctPerson.getDeclaredMethod("setFirstName"); method.insertBefore("updatedFields.add(\"firstName\");"); ctPerson.toClass(); } public static void main(String[] args) throws Exception { rewritePersonClass(); Person p = new Person(); p.setFirstName("foo"); Field field = Person.class.getDeclaredField("updatedFields"); field.setAccessible(true); Set<?> s = (Set<?>) field.get(p); System.out.println(s); }
avec aspectj Vous pouvez modifier des méthodes et des champs avec des conseils.
mon exemple est écrit avec un exemple avec une classe de personne simple et un référentiel de sténer. Toutes les informations sur lesquelles les champs sont mis à jour sont traités par un aspect appelé setTère. Il surveille les champs mis à jour lorsque les champs sont écrits. P> Les autres conseils de cet exemple sont autour de la méthode de mise à jour dans le référentiel. Il s'agit de récupérer les données collectées à partir du premier aspect. P> La classe de la personne: p> le référentiel de stub: p> La sortie pour exécuter la méthode Mise à jour des champs suivants sur personne
Dans le référentiel: [Nom,
Prénom] p>
BlockQuote> Important à noter Voici que la méthode principale appelle sur le L'aspect qui surveille toutes les écrits à des champs privés dans le paquet de démonstration: P> @Aspectj code> Syntaxe qui modifie le code au moment de la compilation ou à la charge de charge. Si vous souhaitez utiliser la modification au moment de l'exécution, vous pouvez utiliser le Spring AOP qui prend également en charge cette syntaxe
@Aspectj code>. P>
Main () Code> dans la classe de la personne avec AspectJ: P>
dtorepository.update (t t) code> mais le
dtorepository.update (t t t t t > Mises à jour des champs) code> est exécuté en raison des conseils autour de l'aspect du référentiel. P>
public class UpdatedObject {
private Map<String, Object> updatedFields =
new HashMap<String, Object>();
public boolean containsField(String fieldName) {
return updatedFields.containsKey(fieldName);
}
public void add(String fieldName) {
updatedFields.put(fieldName, fieldName);
}
public Set<String> getUpdatedFields() {
return Collections.unmodifiableSet(
updatedFields.keySet());
}
}
Voulez-vous dire de manière dynamique au moment de l'exécution?
Probablement au moment de l'exécution, mais cela pourrait même se produire à la compilation. Je ne veux tout simplement pas le coder de manière à ce que je dois tout faire à nouveau tout si je me suis mis à changer comment elle est mise en œuvre
"(Pour l'efficacité d'empêcher de manipuler l'ensemble)" Ce serait le dernier préoccupation de votre efficacité. Cela me semble que vous souhaitez modifier une méthode en quelque sorte au moment de l'exécution? Je serais il y a 100 meilleures solutions à votre problème.
@Ed Swangren - Quelle serait une meilleure solution? J'étais sous l'impression que l'ensemble doit itération sur les caractères de la chaîne afin de le hacher, puis faire une insertion quelque part autour de O (logn)?
Avez-vous des millions d'attributs tels que
prénom code> pour optimiser le
ajouter code> méthode de l'ensemble?
@True Soft - Non, je ne le fais pas. Mais il y avait une certaine préoccupation à propos de devoir faire beaucoup de manipulations sur les objets pour signaler et quoi - non. Je n'aurais pas dû inclus l'optimisation dans le code exemple. La clé est que j'ai besoin de marquer quels champs ont été mis à jour afin que le magasin de données sait quelles propriétés à écraser.