lang:java:aspectj
Différences
Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentesRévision précédenteProchaine révision | Révision précédente | ||
lang:java:aspectj [2016/12/14 23:25] – Ajout de "Mélange avec annotation et sans annotation" root | lang:java:aspectj [2020/04/26 22:39] (Version actuelle) – Conversion de <note> vers <WRAP> root | ||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
- | [[http:// | + | [[http:// |
- | [[https:// | + | [[https:// |
=====Déclaration d'un aspect===== | =====Déclaration d'un aspect===== | ||
+ | Sans annotation | ||
<code java> | <code java> | ||
public aspect Log { | public aspect Log { | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Avec annotation | ||
+ | <code java> | ||
+ | import org.aspectj.lang.annotation.Aspect; | ||
+ | |||
+ | @Aspect | ||
+ | public class Log { | ||
} | } | ||
</ | </ | ||
=====Déclaration d'un point de coupe===== | =====Déclaration d'un point de coupe===== | ||
+ | Sans annotation | ||
<code java> | <code java> | ||
pointcut evaluation(EventHandler h): target(h) && | pointcut evaluation(EventHandler h): target(h) && | ||
call(public void *.handleEvent()); | call(public void *.handleEvent()); | ||
+ | </ | ||
+ | |||
+ | La dénomination exacte pour trouver le nom d'un méthode est : '' | ||
+ | |||
+ | |||
+ | Avec annotation | ||
+ | <code java> | ||
+ | @Pointcut(" | ||
+ | private void CoupureIncI(int x, C c) { | ||
+ | } | ||
</ | </ | ||
Ligne 39: | Ligne 60: | ||
La méthode '' | La méthode '' | ||
- | [[http:// | + | [[http:// |
* '' | * '' | ||
Pour le constructeur, | Pour le constructeur, | ||
+ | |||
=====Déclaration d'un advice===== | =====Déclaration d'un advice===== | ||
Utilisation d'un point de coupe (advice) : | Utilisation d'un point de coupe (advice) : | ||
Ligne 54: | Ligne 76: | ||
<code java> | <code java> | ||
- | around() : call(Display.update()) { if (! Display.disabled()) proceed();} | + | // Si la fonction update ne renvoie rien. |
+ | around() : call(Display.update()) { | ||
+ | | ||
+ | | ||
+ | } | ||
+ | |||
+ | // Si la fonction update renvoie quelque chose. | ||
+ | Object around() : call(Display.update()) { | ||
+ | if (! Display.disabled()) | ||
+ | return proceed(); | ||
+ | return null; | ||
+ | } | ||
</ | </ | ||
Ici, le point de coupe est directement directement défini dans l' | Ici, le point de coupe est directement directement défini dans l' | ||
- | Exemple sans annotation : | ||
<code java> | <code java> | ||
+ | @Around(" | ||
+ | // Mettre void à la place de Object si la méthode setAge ne renvoie rien | ||
+ | public Object twiceAsOld(ProceedingJoinPoint thisJoinPoint, | ||
+ | // En cas de méthode static, pas besoin de joinPoint.getTarget(). | ||
+ | return thisJoinPoint.proceed(new Object[]{i*2, | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Exemple sans annotation : | ||
+ | <file java Log.aj> | ||
public aspect Log { | public aspect Log { | ||
pointcut evaluation(EventHandler h): target(h) && | pointcut evaluation(EventHandler h): target(h) && | ||
call(public void *.handleEvent()); | call(public void *.handleEvent()); | ||
- | // Le pointcut et after ont la même signature. Je ne sais pas si c' | + | // Le pointcut et after ont la même signature, sinon, ce n' |
- | // indispensable mais ça a toujours été le cas dans les exemples que j'ai trouvé. | + | // de capturer des éléments |
after(EventHandler h): | after(EventHandler h): | ||
System.out.println(" | System.out.println(" | ||
} | } | ||
} | } | ||
- | </code> | + | </file> |
- | <code java> | + | <file java ProceedAspect.aj> |
public aspect ProceedAspect { | public aspect ProceedAspect { | ||
pointcut setAge(int i): call(* setAge(..)) && args(i); | pointcut setAge(int i): call(* setAge(..)) && args(i); | ||
Object around(int i): setAge(i) { | Object around(int i): setAge(i) { | ||
+ | // Les trois variables thisJoinPoint, | ||
+ | // s' | ||
return proceed(i*2); | return proceed(i*2); | ||
} | } | ||
} | } | ||
- | </code> | + | </file> |
Et en version annotation Java 5 : | Et en version annotation Java 5 : | ||
- | <code java> | + | <file java Log.java> |
import org.aspectj.lang.annotation.After; | import org.aspectj.lang.annotation.After; | ||
import org.aspectj.lang.annotation.Aspect; | import org.aspectj.lang.annotation.Aspect; | ||
Ligne 89: | Ligne 133: | ||
@Aspect | @Aspect | ||
public class Log { | public class Log { | ||
- | @After(" | + | @After(" |
- | public void LogHandleEvent(EventHandler h) | + | // Chacun des champs est facultatif. |
+ | public void LogHandleEvent(JoinPoint thisJoinPoint, | ||
+ | JoinPoint.StaticPart thisJoinPointStaticPart, | ||
+ | JoinPoint.EnclosingStaticPart thisEnclosingJoinPointStaticPart) | ||
{ | { | ||
System.out.println(" | System.out.println(" | ||
} | } | ||
} | } | ||
- | </code> | + | </file> |
- | <code java> | + | <file java ProceedAspect.aj> |
@Aspect | @Aspect | ||
public class ProceedAspect { | public class ProceedAspect { | ||
Ligne 105: | Ligne 152: | ||
@Around(" | @Around(" | ||
+ | // Dans le cas d'un Around, JoinPoint est en fait un ProceedingJoinPoint. | ||
public Object twiceAsOld(ProceedingJoinPoint thisJoinPoint, | public Object twiceAsOld(ProceedingJoinPoint thisJoinPoint, | ||
- | return thisJoinPoint.proceed(new Object[]{i*2}); | + | return thisJoinPoint.proceed(new Object[]{i*2}); |
} | } | ||
} | } | ||
- | </code> | + | </file> |
- | Séparation du point de coupure et de l' | + | Séparation du point de coupure et de l' |
<code java> | <code java> | ||
Ligne 132: | Ligne 180: | ||
</ | </ | ||
+ | =====Mots clés disponibles dans un advice===== | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | |||
+ | Exemple avec '' | ||
+ | getArgs - 50 // Ici, un seul argument : un entier. | ||
+ | getKind - method-call | ||
+ | getTarget - test.C@30f39991 | ||
+ | getThis - null | ||
+ | getSignature - void test.C.incI(int) | ||
+ | toString - call(void test.C.incI(int)) | ||
+ | toLongString - call(void test.C.incI(int)) | ||
+ | toShortString - call(C.incI(..)) | ||
+ | getSourceLocation - C.java:18 | ||
+ | |||
+ | Exemple avec '' | ||
+ | getId - 0 | ||
+ | getKind - method-call | ||
+ | toLongString - call(void test.C.incI(int)) | ||
+ | toShortString - call(C.incI(..)) | ||
+ | getClass - class org.aspectj.runtime.reflect.JoinPointImpl$StaticPartImpl | ||
+ | getSignature - void test.C.incI(int) | ||
+ | getSourceLocation - C.java:18 | ||
+ | |||
+ | Exemple avec '' | ||
+ | getId - 1 | ||
+ | getKind - method-execution | ||
+ | toLongString - execution(public static void test.C.main(java.lang.String[])) | ||
+ | toShortString - execution(C.main(..)) | ||
+ | toString - execution(void test.C.main(String[])) | ||
+ | getSignature - void test.C.main(String[]) | ||
+ | getSourceLocation - C.java:16 | ||
=====Accéder aux champs privés===== | =====Accéder aux champs privés===== | ||
Mot clé : '' | Mot clé : '' | ||
Ligne 151: | Ligne 232: | ||
C'est niet. | C'est niet. | ||
- | <note warning>Il est interdit de mélanger l' | + | <WRAP center round alert 60%> |
+ | Il est interdit de mélanger l' | ||
+ | |||
+ | < | ||
+ | </WRAP> | ||
<file java C.java> | <file java C.java> | ||
Ligne 460: | Ligne 545: | ||
if (((C) joinPoint.getTarget()).i + x > MAX) | if (((C) joinPoint.getTarget()).i + x > MAX) | ||
throw new RuntimeException(); | throw new RuntimeException(); | ||
- | // En cas de méthode static, pas besion | + | // En cas de méthode static, pas besoin |
joinPoint.proceed(new Object[] { x, joinPoint.getTarget() }); | joinPoint.proceed(new Object[] { x, joinPoint.getTarget() }); | ||
} | } | ||
Ligne 723: | Ligne 808: | ||
} | } | ||
</ | </ | ||
- | <note>Il n'y a finalement pas de différence entre la méthode avec annotation et sans annotation, hormis que l' | + | |
+ | <WRAP center round info 60%> | ||
+ | Il n'y a finalement pas de différence entre la méthode avec annotation et sans annotation, hormis que l' | ||
+ | </WRAP> | ||
=====Héritage et interface===== | =====Héritage et interface===== | ||
<code java> | <code java> | ||
Ligne 756: | Ligne 845: | ||
} | } | ||
</ | </ | ||
+ | |||
+ | =====Aspect à l' | ||
+ | Pour cela, il faut un JAR contenant l' | ||
+ | ====La classe ==== | ||
+ | Créez un '' | ||
+ | <file java C.java> | ||
+ | package classe; | ||
+ | |||
+ | public class C { | ||
+ | public int i = 0; | ||
+ | |||
+ | public void incI(int x) { | ||
+ | i = i + x; | ||
+ | } | ||
+ | |||
+ | static public void main(String[] arg) { | ||
+ | for (String string : arg) { | ||
+ | System.out.println(string); | ||
+ | } | ||
+ | C c = new C(); | ||
+ | c.incI(50); | ||
+ | c.incI(1000); | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | Puis en console allez dans le dossier '' | ||
+ | <code bash> | ||
+ | jar cf C.jar classe | ||
+ | </ | ||
+ | |||
+ | ====L' | ||
+ | Créez un '' | ||
+ | <file java A.aj> | ||
+ | package aspects; | ||
+ | |||
+ | import org.aspectj.lang.ProceedingJoinPoint; | ||
+ | import org.aspectj.lang.annotation.Around; | ||
+ | import org.aspectj.lang.annotation.Aspect; | ||
+ | import org.aspectj.lang.annotation.Pointcut; | ||
+ | |||
+ | import classe.C; | ||
+ | |||
+ | // Les deux implémentations marchent. | ||
+ | |||
+ | public aspect A { | ||
+ | static final int MAX = 1000; | ||
+ | |||
+ | before(int x, C c): call(void C.incI(int)) && target(c) && args(x) { | ||
+ | System.out.println(" | ||
+ | if (c.i + x > MAX) | ||
+ | throw new RuntimeException(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /* | ||
+ | @Aspect | ||
+ | public class A { | ||
+ | private static final int MAX = 1000; | ||
+ | |||
+ | @Around(" | ||
+ | // AutourDeCoupureIncI renvoie le même type que C.incI. | ||
+ | public void AutourDeCoupureIncI(ProceedingJoinPoint joinPoint, int x) throws Throwable { | ||
+ | System.out.println(" | ||
+ | if (((C) joinPoint.getTarget()).i + x > MAX) | ||
+ | throw new RuntimeException(); | ||
+ | |||
+ | joinPoint.proceed(new Object[] { x }); | ||
+ | System.out.println(" | ||
+ | } | ||
+ | } | ||
+ | */ | ||
+ | </ | ||
+ | La classe dépendant de C, il ne faut pas oublie d' | ||
+ | |||
+ | Puis en console allez dans le dossier '' | ||
+ | <code bash> | ||
+ | jar cf A.jar aspects | ||
+ | </ | ||
+ | |||
+ | ====La classe exécutrice==== | ||
+ | Créez un '' | ||
+ | <file java Main.java> | ||
+ | package main; | ||
+ | |||
+ | import java.io.IOException; | ||
+ | import java.lang.reflect.InvocationTargetException; | ||
+ | import java.lang.reflect.Method; | ||
+ | import java.net.URL; | ||
+ | |||
+ | import org.aspectj.weaver.loadtime.WeavingURLClassLoader; | ||
+ | |||
+ | public class Main { | ||
+ | static public void main(String[] arg) throws ClassNotFoundException, | ||
+ | SecurityException, | ||
+ | try (WeavingURLClassLoader weaving = new WeavingURLClassLoader( | ||
+ | new URL[] { new URL(" | ||
+ | new URL[] { new URL(" | ||
+ | Thread.currentThread().getContextClassLoader())) { | ||
+ | Thread.currentThread().setContextClassLoader(weaving); | ||
+ | |||
+ | Class<?> | ||
+ | |||
+ | Method mainMethod = classC.getMethod(" | ||
+ | |||
+ | mainMethod.invoke(null, | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Pensez à ajouter le jar '' | ||
+ | |||
+ | ====Exécution==== | ||
+ | Start | ||
+ | Before | ||
+ | Before | ||
+ | Exception in thread " | ||
+ | at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) | ||
+ | at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java: | ||
+ | at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java: | ||
+ | at java.lang.reflect.Method.invoke(Method.java: | ||
+ | at main.Main.main(Main.java: | ||
+ | Caused by: java.lang.RuntimeException | ||
+ | at aspects.A.ajc$before$aspects_A$1$ff7f72c0(A.aj: | ||
+ | at classe.C.main(C.java: | ||
+ | ... 5 more | ||
+ | |||
+ | ====Commentaires==== | ||
+ | Il est impératif que le projet '' | ||
+ | |||
+ | [[https:// |
lang/java/aspectj.1481754329.txt.gz · Dernière modification : 2016/12/14 23:25 de root