Java Gurus,
Je suis assez nouveau pour annotations
et je ne l'ai pas beaucoup recherché, alors soyez indulgent avec moi ...
Je souhaite implémenter un Custom Annotation
qui va intercept
un appel de méthode; pour commencer avec quelque chose de très basique, il suffit d'imprimer le nom et les paramètres des méthodes afin que je puisse éviter l'instruction logger
.
Un exemple d'appel comme celui-ci:
public MyAppObject findMyAppObjectById(Long id) throws MyCustomException {
log.debug("in findMyAppObjectById(" + id + ")");
//....
}
peut être converti en:
@LogMethodCall(Logger.DEBUG)
public MyAppObject findMyAppObjectById(Long id) throws MyCustomException {
//....
}
Puis-je avoir quelques indices à ce sujet?
Sur la base de vos réponses à mes commentaires, vous ne pourrez pas le faire avec juste des annotations. Vous pouvez, bien sûr, créer vos annotations et créer du code réfléchissant qui sera ensuite détecté et exécuter du code, mais cela ne changera pas trop votre code, car vous devrez appeler la méthode parser
avant d'appeler vos méthodes et je pense que cela ne vous aidera pas trop, car vous devrez appeler la méthode de l'analyseur avant chaque appel.
Si vous avez besoin du comportement que vous avez mentionné (appel automatique), vous devrez combiner vos annotations avec un cadre AOP comme Spring (Java simple) ou AspectJ (code AspectJ). Ensuite, vous pouvez définir des coupes de points et chaque fois que ce point est atteint, du code peut être exécuté. Vous pouvez ensuite configurer pour exécuter du code avant et/ou après l'exécution de la méthode.
Si le premier scénario est suffisant, vous pouvez faire quelque chose comme:
Enregistreur: enum
public enum Logger {
INFO,
DEBUG;
}
LogMethodCall: annotation
import Java.lang.annotation.ElementType;
import Java.lang.annotation.Retention;
import Java.lang.annotation.RetentionPolicy;
import Java.lang.annotation.Target;
@Retention( RetentionPolicy.RUNTIME ) // the annotation will be available during runtime
@Target( ElementType.METHOD ) // this can just used in methods
public @interface LogMethodCall {
Logger logLevel() default Logger.INFO;
}
Personne: classe annotée
public class Person {
// will use the default log level (INFO)
@LogMethodCall
public void foo( int a ) {
System.out.println( "foo! " + a );
}
@LogMethodCall( logLevel = Logger.DEBUG )
public void bar( int b ) {
System.out.println( "bar! " + b );
}
}
Utils: classe avec la méthode statique statique (ceci effectuera le "parsing")
public class Utils {
public static void log( Object o, String methodName ) {
// gets the object class
Class klass = o.getClass();
// iterate over its methods
for ( Method m : klass.getMethods() ) {
// verify if the method is the wanted one
if ( m.getName().equals( methodName ) ) {
// yes, it is
// so, iterate over its annotations
for ( Annotation a : m.getAnnotations() ) {
// verify if it is a LogMethodCall annotation
if ( a instanceof LogMethodCall ) {
// yes, it is
// so, cast it
LogMethodCall lmc = ( LogMethodCall ) a;
// verify the log level
switch ( lmc.logLevel() ) {
case INFO:
System.out.println( "performing info log for \"" + m.getName() + "\" method" );
break;
case DEBUG:
System.out.println( "performing debug log for \"" + m.getName() + "\" method" );
break;
}
}
}
// method encountered, so the loop can be break
break;
}
}
}
}
AnnotationProcessing: classe avec code pour tester le traitement des annotations
public class AnnotationProcessing {
public static void main(String[] args) {
Person p = new Person();
Utils.log( p, "foo" );
p.foo( 2 );
Utils.log( p, "bar" );
p.bar( 3 );
}
}
Bien sûr, vous devrez améliorer mon code pour l'adapter à vos besoins. Ce n'est qu'un point de départ.
En savoir plus sur les annotations:
En savoir plus sur AOP:
Utilisez Spring AOP avec Java Annotation. Spring AOP annule la nécessité d'écrire une classe util pour l'analyse des classes Java à l'aide de Java Reflection.
Exemple -
Annotation personnalisée -
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface A {
boolean startA() default false;
boolean endA() default false;
}
Aspect-
@Aspect
public class AAspect {
@Pointcut(value = "execution(* *.*(..))")
public void allMethods() {
LOGGER.debug("Inside all methods");
}
@Before("allMethods() && @annotation(A)")`
public void startAProcess(JoinPoint pjp, A a) throws Throwable {
if (a.startA()) {
//Do something
}
}
Activer AspectJ -
@Configuration
@EnableAspectJAutoProxy
public class AConfig {
}
Utilisation dans le code -
@A(startA = true, endA = true)
public void setUp(){
//Do something- logic
}
Comme déjà suggéré, l'AOP et les annotations sont la meilleure option. Je recommanderais d'utiliser un mécanisme prêt à l'emploi de jcabi-aspects (je suis développeur):
@Loggable(Loggable.DEBUG)
public String load(URL url) {
return url.openConnection().getContent();
}
Tous les appels de méthode seront enregistrés sur SLF4J.