Cómo establecer el valor de una propiedad mediante personalizada de Java anotación y Spring AOP?

0

Pregunta

Me gustaría usar personalizada de Java anotación para insertar un valor en un privado de la propiedad de clase utilizando Spring AOP (y/o AspectJ). Ejemplo rápido:

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();
    }
    ...
}

Qué me gustaría que pasara?

Voy a llamar y entrar en la getVarExample() y después devuelve me gustaría ver "helloworld" en la consola o de registro. Me gustaría de alguna manera la var1 a un valor personalizado el uso de AOP. Cualquier variable de propiedad que serán anotados con @MyAnnotation "pasará a ser "helloworld". Espero que el ejemplo anterior es clara.

Lo he intentado?

De hecho estoy seguro que no hay ningún error en los nombres de los paquetes, también jugueteó con diferentes AOP asesoramiento anotaciones como @Around y @Before. También probé con diferentes objetivos en la MyAnnotation y terminó con ElementType.FIELD cual debe ser la correcta.

Me pueden ayudar a conseguir trabajo?

Sé que esto se puede hacer, pero no podía encontrar ningún ejemplo de trabajo en línea. De nuevo, me gustaría ver 2 respuestas:

1. Cómo obtener el pointcut para desencadenar en MyController entrada? Quiero coger un punto de interrupción dentro de la enrichVar1(..) método de la MyAspect clase.

2. ¿Cómo puedo modificar el anotado var1 valor enenrichVar1(..) método de la MyAspect la clase?

No sé qué estoy haciendo mal. Cualquier ayuda será muy apreciada. Gracias!

La AOP está configurado correctamente en mi proyecto. Yo lo sé porque yo ya estoy para el uso de AOP para diferentes cosas (tala de árboles, por ejemplo).

Actualización #1:

Por favor, tenga en cuenta que no hay captadores o incubadoras para el var1 variable privada. La variable que va a ser utilizado dentro de la MyControllerImpl. Para ilustrar esto mejor que he cambiado el valor de retorno de la getVarExample.

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

Mejor respuesta

3

Como dije en mi comentario:

El pointcut designador @annotation() intercepta anotado métodos, no anotado campos. Para que, nativo de AspectJ ha get() y set(). I. e., el pointcut también tendría que ser cambiado si la migración a AspectJ. Pero estoy de acuerdo en que se pegue a Spring AOP y anotación de métodos getter en lugar de campos es, probablemente, suficiente aquí.

Pero ya que insisten en que desea mantener la clase de controlador sin cambios, aquí es el nativo de AspectJ solución. Por favor, lea el capítulo Uso de AspectJ con Aplicaciones de Primavera para saber cómo configurar que con @EnableLoadTimeWeaving y JVM parámetro -javaagent:/path/to/aspectjweaver.jar.

Con el fin de demostrar que realmente esta solución funciona de forma independiente de la Primavera, la estoy usando sin Muelle clases o anotaciones a todos, sólo a los POJOs y nativo de AspectJ. Usted puede simplemente hacer lo mismo dentro de su Primavera de la aplicación. Por favor, tenga en cuenta que los nativos AspectJ aspectos no necesita @Component las anotaciones, en contraste con Spring AOP aspectos.

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";
  }
}

Cuando se ejecuta Applicationel registro de la consola va a ser:

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

El AspectJ manual se explica la sintaxis de campo get y set unirse a punto de firmas y de campo de los patrones.


Nota: creo que el caso de uso, podría ser un hack en lugar de una aplicación válida de diseño. Usted debe refactorizar en lugar de piratear una aplicación como esta.

2021-11-24 21:34:25

Quiero agradecer a usted! Esto es lo que yo estaba buscando y me tomó muy mucho de experimentar para conseguir trabajo. Todavía no sé cómo incorporar en la Primavera correctamente, pero eso es para otro tema. Gracias por su tiempo y generosidad es el tuyo!
user3732445
0

Como el que va desde la Primavera docs Spring AOP de que el apoyo de la Primavera en las judías de la ejecución del método unir los puntos. Para hacer el campo de acceso a unirse a los puntos de trabajo que usted necesita para utilizar AspectJ del backend con el tiempo de carga de tejido para la AOP.

Pero para tu caso no es necesario que utilice el campo de unir los puntos, usted puede poner su anotación en el captador y esto debería funcionar.

2021-11-24 20:53:57

Exactamente. Por CIERTO, el pointcut designador @annotation() intercepta anotado métodos, no anotado campos. Para que, nativo de AspectJ ha get() y set(). I. e., el pointcut también tendría que ser cambiado si la migración a AspectJ. Pero estoy de acuerdo en que se pegue a Spring AOP y anotación de métodos getter en lugar de campos es, probablemente, suficiente aquí.
kriegaex

@geobreze agradezco su respuesta, pero esto no es útil. He encontrado el enlace por mí mismo, y no hay ningún ejemplo de trabajo para mi caso.
user3732445

En otros idiomas

Esta página está en otros idiomas

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