2016-10-29 1 views
0

Je voudrais créer un pointcut sur la classe d'échantillon suivante à chaque fois qu'une variable est assignée. Par exemple, dans method1 (nombre entier), this.x est défini sur int. Je réalise dans ce cas que je pourrais juste faire un pointcut sur method1 et ensuite découvrir ce que la nouvelle valeur x utilise la réflexion. Cependant, je me demandais s'il y avait un moyen de faire un point sur la ligne this.x = nombre, de sorte que mon pointcut est déclenché, par exemple, avant que la fonction se termine?coupes d'aspectj sur l'affectation de variable d'objet

public class Sample { 
private int x; 

public void method1(int number) { 
    this.x = number; 
} 

public int getX() { 
    return this.x; 
} 

public void method1(int number, String value) { 
    this.x = number; 
} 

public void method2(String value) { 
    this.x = 105; 
} 
} 
+0

Vous ne pouvez pas faire un pointcut à une ligne de code particulière. Seulement sur les méthodes. – Heri

Répondre

1

Vous pouvez le faire avec soit:

  • un aspect privilégié:

    import java.lang.reflect.Field; 
    import org.aspectj.lang.reflect.FieldSignature; 
    
    public privileged aspect FieldChangeMonitorAspect { 
    
        void around(Sample sample): set(int Sample.x) && target(sample) { 
         FieldSignature fieldSignature = (FieldSignature) thisJoinPoint.getSignature(); 
         Field field = fieldSignature.getField(); 
    
         int oldValue = sample.x; 
         int newValue = ((Integer)thisJoinPoint.getArgs()[0]).intValue(); 
         proceed(sample); 
         int actualNewValue = sample.x; 
    
         System.out.printf("changed field %s: old value=%d, new value=%d, " 
           + "actual new value=%d\n", 
           field, oldValue, newValue, actualNewValue); 
        } 
    
    } 
    
  • un aspect non-privilégié de réflexion en utilisant:

    import java.lang.reflect.Field; 
    import org.aspectj.lang.reflect.FieldSignature; 
    
    public aspect FieldChangeMonitorAspectWithReflection { 
    
        void around(Sample sample): set(int Sample.x) && target(sample) { 
         FieldSignature fieldSignature = (FieldSignature) thisJoinPoint.getSignature(); 
         Field field = fieldSignature.getField(); 
         try { 
          Object oldValue = field.getInt(sample); 
          Object newValue = thisJoinPoint.getArgs()[0]; 
          proceed(sample); 
          Object actualNewValue = field.get(sample); 
    
          System.out.printf("changed field %s: old value=%d, new value=%d, " 
            + "actual new value=%d\n", 
            field, oldValue, newValue, actualNewValue); 
         } catch (IllegalArgumentException | IllegalAccessException e) { 
          throw new RuntimeException(e); 
         } 
        } 
    
    } 
    

La première version (privilégiée) est recommandée lorsque vous devez surveiller un champ connu d'un type connu, car il est plus rapide en n'utilisant pas de réflexion. Toutefois, lorsque vous devez surveiller des champs qui ne sont pas connus au moment de l'écriture (par exemple, marqués par une annotation) ou qu'il existe plusieurs champs que vous souhaitez surveiller dans plusieurs types possibles, la seconde version peut s'avérer utile.

Non que newValue et actualNewValue devrait toujours avoir la même valeur, mais le newValue est disponible avant de changer la valeur du champ, alors que actualNewValue ne peut être obtenu après que la valeur du champ a été modifié.