Eigene Annotations, Pre-/Post-/Call-Method

Das Ziel ist es 3 Annoations zu schreiben, die je nachdem vor oder nach einen Methodenaufruf eine andere Methode aufruft. Mein Problem ist nur, dass ich zwar mit Annotations arbeite ( Spring Boot, JPA, Lombok, ... ) aber noch nie eigene geschrieben habe. Bin da nicht so sehr spezalisiert in Java.

Deswegen bitte ich einen erfahreneren Programmierer mir mal ein Beispiel Prozessor zu schreiben wie das funktionieren könnte. Dürfte ja kein großer Aufwand sein.

Anforderung: Das Method-Calling sollte/ braucht eigentlich nur innerhalb einer Klassenstruktur(mit Vererbung) funktionieren und mit einer id.

Wieso das ganze? Ich weiß, man kann auch einfach die Methode in der Methode aufrufen, aber da ich mit Lombok arbeite (@Getter, @Setter) und bei jeder Setter-Methode die andere Methode aufgerufen werden soll.


Java:
public class Example{
  
  private Object object;
  ....

  @PostMethod("method-id")
  public void setObject(Object object){
    ...
  }

  //Es dürfen keine Parameter verwendet werden.
  @CallMethod("method-id")
  private void save(){
    ...
  }
Java:
@Setter(onMethod={@PostMethod})
public class Example{
   
  private Object object;
  ....

  //Es dürfen keine Parameter verwendet werden.
  @CallMethod("method-id")
  private void save(){
    ...
  }
Java:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface PreMethod {
    String method();
}
Java:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface PostMethod {
    String method();
}
Java:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface CallMethod {
    String method();
}
Java:
//Quelle: http://icancode.de/3448/eigene-java-annotations-teil-1 abgewandelt
@SupportedAnnotationTypes({"CallMethod", "PostMethod", "PreMethod"})
public class CallMathodProcessor extends AbstractProcessor {


    // utils
    Types types;
    Elements elems;

    @Override
    public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
        return false;
    }

    private void processAnnotation(Element method, Messager msg) {
        final CallMethod ann = method.getAnnotation(CallMethod.class);
        // check basic properties
        if (method.getKind() != ElementKind.METHOD) {
            error("annotation only for methods", method);
        }
        // check types
        final ExecutableType emeth = (ExecutableType) method.asType();
        if (not(emeth.getReturnType().getKind().equals(TypeKind.BOOLEAN))) {
            error("annotated Element must have return type boolean", method);
        }
        if (emeth.getParameterTypes().size() != 1) {
            error("annotated Element must have exactly one parameter", method);
        } else {
            final TypeMirror param0 = emeth.getParameterTypes().get(0);
            final TypeMirror string = elems.getTypeElement(String.class.getCanonicalName()).asType();
            final boolean isSame = types.isSameType(param0, string);
            if (not(isSame)) {
                error("annotated Element must have exactly one String parameter", method);
            }
        }

    }
    /** @param where will be used to present a position hint in the compiler message,  if null its a position-less message */
    void error(String msg, Element where) {
        processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, msg, where);
    }
    private static boolean not(boolean val) { return !val; }

}
 
Was du haben möchtest nennt sich AOP (Aspect Oriented Programming) und wird von AspektJ z.B. implementiert.

Einen kleinen Teil könnte man mit Proxy machen, aber wieso das Rad immer neu erfinden.
Deswegen bitte ich einen erfahreneren Programmierer mir mal ein Beispiel Prozessor zu schreiben wie das funktionieren könnte. Dürfte ja kein großer Aufwand sein.
Wenn es kein großer Aufwand wäre, dann könntest du es eben selbst machen?
Bei genauerer Problemstellung kannst du gegen Entgeld gerne um konkrete Hilfe/Implementierung bitten.
 
AspectJ kannte ich noch nicht, aber wenn AspectJ sowas kann dann hab ich doch schon meine Lösung.

Wenn es kein großer Aufwand wäre, dann könntest du es eben selbst machen?
Wenn ich mich in die Problematik der Annotationprogrammierung einarbeiten würde, dann nicht aber ich wollte mich halt nicht erstmal Stundenlang mit Annotationprogrammierung rumärgern für ein bisschen Schreibfaulheit.
 
So etwas wie "Annotationprogrammierung" gibt es nicht. Das ist wie "Instanzvariablenprogrammierung" oder "Methodenparameterprogrammierung". Annotationen sind an sich ja nichts besonderes. Nur Java-Klassen mit spezieller Syntax, um sie an andere Syntaxelemente von Java anzuheften. Und mehr auch nicht.
Das, was sie nützlich/nutzbar machen, ist z.B. die ja bereits von @Flown erwähnte aspektorientierte Programmierung oder z.B. Reflection.
 
So etwas wie "Annotationprogrammierung" gibt es nicht. Das ist wie "Instanzvariablenprogrammierung" oder "Methodenparameterprogrammierung".
Ich geb es zu ich hätte es auch in Anführungsstrichen schreiben sollen um mein Unwissen in der Fachsprache kenntlich zu machen.
Soweit ich weiß gibt es aber auch nur in Java so eine Handhabung mit Annotation.
Da fehlt doch nur noch "Klassenprogrammierung", was eigentlich nur ein doofes Wort für OOP wäre.
 
C# (bzw. .Net CIL) hat auch Annotations (gleiches Konzept), nur nennen sie sie dort "Attributes".
TypeScript hat so etwas ähnliches (zumindest von der Syntax her - und hoffentlich bald ECMAScript Standard), und sie nennen es "Decorators".
Generell fällt so etwas in den Bereich der Metaprogrammierung.
 

Zurück
Oben