Quiero monitorear todos los métodos públicos de todas las clases con la anotación especificada (digamos @Monitor) (nota: la anotación es a nivel de clase). ¿Cuál podría ser un punto de corte posible para esto? Nota: Estoy usando @AspectJ style Spring AOP.@AspectJ punto de corte para todos los métodos de una clase con anotación específica
Respuesta
Algo así:
@Before("execution(* com.yourpackage..*.*(..))")
public void monitor(JoinPoint jp) {
if (jp.getTarget().getClass().isAnnotationPresent(Monitor.class)) {
// perform the monitoring actions
}
}
Tenga en cuenta que no debe tener ningún otro tipo sobre la misma clase antes de ésta, debido a que las anotaciones se perderán después de proxy.
Debe combinar un punto de corte con un punto de corte de método.
Estos puntos de corte va a hacer el trabajo para encontrar todos los métodos públicos dentro de una clase marcada con una anotación @Monitor:
@Pointcut("within(@org.rejeev.Monitor *)")
public void beanAnnotatedWithMonitor() {}
@Pointcut("execution(public * *(..))")
public void publicMethod() {}
@Pointcut("publicMethod() && beanAnnotatedWithMonitor()")
public void publicMethodInsideAClassMarkedWithAtMonitor() {}
Consejo el último punto de corte que combina los dos primeros y ya está!
Si usted está interesado, he escrito un cheat sheet con el estilo @AspectJ aquí con un example document correspondiente aquí.
Gracias. La discusión de los puntos de anotación en su Cheat Sheet es particularmente útil. – GregHNZ
¿Cómo obtengo una referencia a la clase en el consejo de la manera en que lo hago con consejos de punto de corte normal? @Antes ("onObjectAction() && this (obj)") – expressions
La Hoja de trucos fue muy útil, a pesar de que han pasado 5 años :) –
También puede definir el punto de corte como
public pointcut publicMethodInsideAClassMarkedWithAtMonitor() : execution(public * (@Monitor *).*(..));
Poco simple 'ejecución (público * @Monitor *. * (..))' funciona, también. – xmedeko
La forma más sencilla parece ser:
@Around("execution(@MyHandling * com.exemple.YourService.*(..))")
public Object aroundServiceMethodAdvice(final ProceedingJoinPoint pjp)
throws Throwable {
// perform actions before
return pjp.proceed();
// perform actions after
}
Se interceptará la ejecución de todos los métodos anotados específicamente con '@MyHandling' en 'YourService' clase. Para interceptar todos los métodos sin excepción, simplemente coloque la anotación directamente en la clase.
No importa el alcance privado/público aquí, pero tenga en cuenta que spring-aop no puede usar el aspecto para llamadas a métodos en la misma instancia (típicamente privadas), porque no usa la clase proxy en este caso.
Utilizamos el consejo de @Around aquí, pero básicamente es la misma sintaxis con @Before, @ After o cualquier consejo.
Por cierto, anotación @MyHandling debe estar configurado de esta manera:
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.TYPE })
public @interface MyHandling {
}
que no está respondiendo la instrucción original, con ElementType.Type – Alex
sí, ElementType.TYPE también permitirá poner la anotación directamente en las clases, lo que supongo que dará como resultado manejar cualquier método de esta clase. ¿Soy verdad? ¿Realmente está funcionando? – Donatello
El '// realizar acciones después de' nunca se llamará ya que estamos devolviendo el valor en la línea anterior. – josephpconley
El uso de anotaciones, como se describe en la pregunta.
Anotación: @Monitor
anotación en la clase, app/PagesController.java
:
package app;
@Controller
@Monitor
public class PagesController {
@RequestMapping(value = "/", method = RequestMethod.GET)
public @ResponseBody String home() {
return "w00t!";
}
}
anotación en el método, app/PagesController.java
:
package app;
@Controller
public class PagesController {
@Monitor
@RequestMapping(value = "/", method = RequestMethod.GET)
public @ResponseBody String home() {
return "w00t!";
}
}
anotación personalizada, app/Monitor.java
:
package app;
@Component
@Target(value = {ElementType.METHOD, ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface Monitor {
}
Aspecto para la anotación, app/MonitorAspect.java
:
package app;
@Component
@Aspect
public class MonitorAspect {
@Before(value = "@within(app.Monitor) || @annotation(app.Monitor)")
public void before(JoinPoint joinPoint) throws Throwable {
LogFactory.getLog(MonitorAspect.class).info("monitor.before, class: " + joinPoint.getSignature().getDeclaringType().getSimpleName() + ", method: " + joinPoint.getSignature().getName());
}
@After(value = "@within(app.Monitor) || @annotation(app.Monitor)")
public void after(JoinPoint joinPoint) throws Throwable {
LogFactory.getLog(MonitorAspect.class).info("monitor.after, class: " + joinPoint.getSignature().getDeclaringType().getSimpleName() + ", method: " + joinPoint.getSignature().getName());
}
}
Habilitar AspectJ, servlet-context.xml
:
<aop:aspectj-autoproxy />
incluyen bibliotecas AspectJ, pom.xml
:
<artifactId>spring-aop</artifactId>
<artifactId>aspectjrt</artifactId>
<artifactId>aspectjweaver</artifactId>
<artifactId>cglib</artifactId>
Buen ejemplo. Una pregunta: ¿por qué el Annotation 'Monitor' tiene que ser un Spring' Component'? – mwhs
La anotación 'Component' se usa para indicarle al contenedor de Spring que se aplique incluir la clase en el aspecto de weaver AspectJ. Por defecto, Spring solo mira 'Controller',' Service', y otras anotaciones específicas, pero no 'Aspect'. – Alex
Ok gracias. Pero estaba hablando de la anotación '@ Component' en' @ interface' no en 'Aspect'. ¿Por qué es eso necesario? – mwhs
Usted podría utilizar PerformanceMonitoringInterceptor de primavera y programación registrar el consejo usando un procesador de beanpost.
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Monitorable
{
}
public class PerformanceMonitorBeanPostProcessor extends ProxyConfig implements BeanPostProcessor, BeanClassLoaderAware, Ordered,
InitializingBean
{
private Class<? extends Annotation> annotationType = Monitorable.class;
private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
private Advisor advisor;
public void setBeanClassLoader(ClassLoader classLoader)
{
this.beanClassLoader = classLoader;
}
public int getOrder()
{
return LOWEST_PRECEDENCE;
}
public void afterPropertiesSet()
{
Pointcut pointcut = new AnnotationMatchingPointcut(this.annotationType, true);
Advice advice = getInterceptor();
this.advisor = new DefaultPointcutAdvisor(pointcut, advice);
}
private Advice getInterceptor()
{
return new PerformanceMonitoringInterceptor();
}
public Object postProcessBeforeInitialization(Object bean, String beanName)
{
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName)
{
if(bean instanceof AopInfrastructureBean)
{
return bean;
}
Class<?> targetClass = AopUtils.getTargetClass(bean);
if(AopUtils.canApply(this.advisor, targetClass))
{
if(bean instanceof Advised)
{
((Advised)bean).addAdvisor(this.advisor);
return bean;
}
else
{
ProxyFactory proxyFactory = new ProxyFactory(bean);
proxyFactory.copyFrom(this);
proxyFactory.addAdvisor(this.advisor);
return proxyFactory.getProxy(this.beanClassLoader);
}
}
else
{
return bean;
}
}
}
que debería ser suficiente para marcar su método aspecto como éste:
@After("@annotation(com.marcot.CommitTransaction)")
public void after() {
echar un vistazo a this para una guía paso a paso en este sentido.
desde la primavera de AnnotationTransactionAspect
:
/**
* Matches the execution of any public method in a type with the Transactional
* annotation, or any subtype of a type with the Transactional annotation.
*/
private pointcut executionOfAnyPublicMethodInAtTransactionalType() :
execution(public * ((@Transactional *)+).*(..)) && within(@Transactional *);
Uso
@Before("execution(* (@YourAnnotationAtClassLevel *).*(..))")
public void beforeYourAnnotation(JoinPoint proceedingJoinPoint) throws Throwable {
}
- 1. @AspectJ pointcut para subclases de una clase con una anotación
- 2. @AspectJ punto de corte para métodos que anulan un método de interfaz con una anotación
- 3. AspectJ: parámetro en un corte de punto
- 4. Spring AOP - punto de corte para cada método con una anotación
- 5. Cómo hacer coincidir métodos que no tienen una Anotación específica en AspectJ
- 6. pointcut aspectj con la anotación de los parámetros
- 7. ¿Cómo dividir todos los métodos de una clase en GDB?
- 8. Clase abstracta con todos los métodos concretos
- 9. Aspectj @Around pointcut todos los métodos en Java
- 10. cómo mantener todos los métodos en una clase con ProGuard
- 11. Agregue un punto de interrupción de método a todos los métodos de una clase en EclipseIDE
- 12. ¿Cómo puedo obtener el javadoc de todos los métodos con una Anotación específica, con el nombre del método y el nombre del paquete/clase?
- 13. Anotaciones de parámetros de concordancia de corte de aspecto AspectJ en cualquier posición
- 14. Punto de corte AOP Spring que coincide con la anotación en la interfaz
- 15. ¿Cómo encontrar todos los métodos anulando los métodos de superclase/interfaz sin la anotación @Override?
- 16. ¿Cómo repito todos los métodos de una clase en Perl?
- 17. primavera AOP punto de corte para la discusión anotada
- 18. ¿Puedo obtener todos los métodos de una clase?
- 19. jdb punto de corte condicional
- 20. Listar todos los métodos de una clase dada, excluyendo los métodos de la clase padre en PHP
- 21. registrar todos los métodos?
- 22. Congelar todos los hilos en el punto de corte en VS2010
- 23. ¿Cómo puedo acceder a los atributos de los métodos con Spring AOP (estilo AspectJ)?
- 24. Poner todos los métodos en la definición de clase
- 25. expresión de punto de corte AOP para cualquier método público de un servicio
- 26. Definir punto de corte para la función de miembro de la clase no tiene éxito
- 27. ¿Hay algún problema con una clase con todos los métodos estáticos?
- 28. Cómo especificar un único punto de corte para varios paquetes
- 29. Obtener todos los elementos en un documento HTML con una clase CSS específica
- 30. En .NET, ¿puedes usar el reflejo para obtener todos los métodos no heredados de una clase?
El debajo de uno trabaja en una medida. @Pointcut ("execution (* (@ org.rejeev.Monitor *). * (..))") Sin embargo, ahora el aviso se está ejecutando dos veces. ¿Cualquier pista? –
Otro punto es que la anotación @Monitor está en una interfaz y allí una clase implementa eso. ¿La presencia de una interfaz y clase provocará la doble ejecución de tal consejo? –
Debe aceptar la excelente respuesta a continuación. Esto le da reputación. Hay muy pocas personas aquí en SO que pueden responder preguntas de AspectJ. – fool4jesus