Jak nastavit hodnotu vlastnosti pomocí Java vlastní anotace a Spring AOP?

0

Otázka

Chtěl bych použít vlastní Java anotace chcete-li vložit hodnotu v privátní třídy majetku použití Spring AOP (a/nebo AspectJ). Rychlý příklad:

MyAnnotation.java:

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD })
public @interface MyAnnotation {
}

MyController.java:

public class MyControllerImpl implements MyController {

    ...
    
    @MyAnnotation
    private String var1;

    @Override
    public String getVarExample() {
       // imagine this is a REST API that gets called on @GET
       // request and returns a string

       System.out.println(this.var1); // <-- I'd like this to be "helloworld"
                                    // this is just for illustration
                                    // of course, I will want to do 
                                    // something more meaningful with
                                    // the 'var1' variable
       return "ok"; <- unimportant for this example
    }
    ...

MyAspect.java:

@Aspect
@Component
public class MyAspect {

    @Pointcut("@annotation(com.mypackage.annotation.MyAnnotation)")
    public void fieldAnnotatedWithMyAnnotation() {
        
    }

    @Around("fieldAnnotatedWithMyAnnotation()")
    public Object enrichVar1(ProceedingJoinPoint pjp) throws Throwable {
        
        // problem #1 - the program never enters here
        // problem #2 - I need to figure out how to set up the var1 here
        //              to "helloworld" , how?
        return pjp.proceed();
    }
    ...
}

Co bych chtěl, aby se stalo?

Zavolám a dostat se do getVarExample() a po návratu bych rád viděl "helloworld" v konzoli, nebo se přihlásit. Chtěl bych nějak nastavit var1 na vlastní hodnotu pomocí AOP. Žádný majetek proměnnou, která bude komentovaný s @MyAnnotation bude nastavena na "helloworld". Doufám, že výše uvedený příklad je jasný.

Co jsem zkoušel?

Ujistil jsem se, že tam není žádný překlep v názvu balíčku, také si pohrávala s různými AOP poradenství popisy jako @Around a @Before. Zkoušel jsem i různé cíle v MyAnnotation a skončil s ElementType.FIELD což by měla být správná.

Můžete mi pomoci, aby si to funguje?

Vím, že to lze udělat, ale nemohl najít žádné pracovní příklad on-line. Opět bych rád viděl 2 odpovědi:

1. Jak se dostat pointcut pro spuštění na MyController vchod? Chci chytit zarážku uvnitř enrichVar1(..) metoda MyAspect třídy.

2. Jak mohu změnit komentovaný var1 hodnota venrichVar1(..) metoda MyAspect třída?

Nevím, co dělám špatně. Jakákoliv pomoc bude velmi ocenil. Děkuji!!!

AOP je správně nastaven v mém projektu. Vím to, protože jsem už pomocí AOP pro různé věci (protokolování pro příklad).

Update #1:

Prosím, na vědomí, že nejsou getter nebo setter pro var1 soukromé proměnné. Proměnné budou použity pouze v rámci MyControllerImpl. Pro ilustraci lepší jsem změnil návratová hodnota getVarExample.

annotations aspectj java spring
2021-11-22 12:02:25
2

Nejlepší odpověď

3

Jak jsem řekl na můj komentář:

Na pointcut označení @annotation() zachycuje komentovaný metody, není komentovaný pole. Na to, nativní AspectJ má get() a set(). I. e., na pointcut by také muset být změněna, pokud migrují do AspectJ. Ale souhlasím s tím, že držet se Spring AOP a anotace getter metody namísto pole je asi dost.

Ale protože trváte na tom, že chcete, aby správce třídy beze změny, tady je nativní AspectJ řešení. Prosím přečtěte si kapitolu Pomocí AspectJ s Jarní Aplikace pro konfiguraci, že s @EnableLoadTimeWeaving a JVM parametr -javaagent:/path/to/aspectjweaver.jar.

Za účelem prokázání, že toto řešení opravdu funguje nezávisle na Jaře, jsem pomocí žádné Jaro tříd nebo popisy, pouze jednoduché pojo a nativní AspectJ. Můžete jednoduše udělat totéž v rámci své Jarní aplikace. Vezměte prosím na vědomí, že nativní AspectJ aspekty nepotřebují @Component popisy, na rozdíl od Spring AOP aspekty.

package de.scrum_master.app;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD })
public @interface MyAnnotation {}
package de.scrum_master.app;

public interface MyController {
  String getVarExample();
}
package de.scrum_master.app;

public class MyControllerImpl implements MyController {
  @MyAnnotation
  private String var1;

  @Override
  public String getVarExample() {
    System.out.println(this.var1);
    return "ok";
  }
}
package de.scrum_master.app;

public class Application {
  public static void main(String[] args) {
    MyController myController = new MyControllerImpl();
    myController.getVarExample();
  }
}
package de.scrum_master.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class MyAspect {

  @Pointcut("get(@de.scrum_master.app.MyAnnotation * *)")
  public void fieldAnnotatedWithMyAnnotation() {}

  @Around("fieldAnnotatedWithMyAnnotation()")
  public Object enrichVar1(ProceedingJoinPoint pjp) throws Throwable {
    System.out.println(pjp);
    return "helloworld";
  }
}

Při spuštění Application, log konzole bude:

get(String de.scrum_master.app.MyControllerImpl.var1)
helloworld

Na AspectJ příručka vysvětluje syntaxi pole a nastavit připojit bod podpisy a pole vzorce.


Poznámka: myslím, že váš případ použití může být hack, spíše než platná aplikace designu. Byste měli refaktorovat, spíše než se nabourat do aplikace, jako je tento.

2021-11-24 21:34:25

Chci vám poděkovat! To je to, co jsem hledal a trvalo mi velmi hodně experimentování, aby si to práci. Já pořád nevím, jak se začlenit do Jara správně, ale to je na jiný téma. Děkuji za váš čas a odměna je tvoje!
user3732445
0

Jak to jde od Jara docs Spring AOP podporuje Jarní fazole' způsob provedení připojit body. Aby se přístupu k poli připojit body práce budete muset použít AspectJ je backend s load time weaving pro AOP.

Ale pro tvůj případ to není nutné použít pole připojit bodů, můžete si dát své anotace na getter a to by mělo fungovat.

2021-11-24 20:53:57

Přesně. BTW, pointcut označení @annotation() zachycuje komentovaný metody, není komentovaný pole. Na to, nativní AspectJ má get() a set(). I. e., na pointcut by také muset být změněna, pokud migrují do AspectJ. Ale souhlasím s tím, že držet se Spring AOP a anotace getter metody namísto pole je asi dost.
kriegaex

@geobreze já oceňuji vaši odpověď, ale to není užitečné. Našel jsem odkaz sám a není žádný funkční příklad pro můj případ.
user3732445

V jiných jazycích

Tato stránka je v jiných jazycích

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................