2013-07-05 35 views
5

Tôi làm cách nào để nhận chú thích làm đối số cho lời khuyên được xác định cho chú thích cấp lớp ? Có thể không?@AspectJ Lời khuyên chú thích cấp lớp với chú thích làm đối số phương thức

Từ bài đăng here Tôi có thể nhận được điểm cắt xác định tất cả các phương pháp công khai trong lớp được đánh dấu bằng một chú thích cụ thể. Tôi cũng có thể nhận được lời khuyên. Tuy nhiên, tôi không biết cách nhận biến chú thích được chuyển làm đối số trong trường hợp trên.

Đối với chú thích cấp phương pháp, tôi có thể nhận được lời khuyên và lời khuyên trong đó tôi có thể nhận chú thích được chuyển làm đối số, nhưng tôi không biết cách thực hiện tương tự cho chú thích cấp lớp.

Đoạn mã dưới đây hoạt động, nhưng tôi cần nhận chú thích làm đối số cho lời khuyên “LogExecutionTimeByClass” trong chương trình bên dưới và tôi không thể có được lời khuyên hoặc chỉ dẫn thích hợp cho tương tự.

chú giải:

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

@Target({ElementType.TYPE, ElementType.METHOD}) 
@Retention(RetentionPolicy.RUNTIME) 
public @interface LogExecutionTime { 
String level(); 
} 

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 LogTimeAspect { 

    /* 
    * Pointcut to match all the public methods. 
    */ 
    @Pointcut("execution(public * *(..))") 
    public void publicMethod() {} 

    /* 
    * Advice for the public methods that are marked with Annotation "LogExecutionTime" and it works as expected no issue. 
    */ 
    @Around("publicMethod() && @annotation(annotation) ") 
    public Object LogExecutionTimeByMethod(final ProceedingJoinPoint joinPoint,final LogExecutionTime annotation) throws Throwable 
    { 
     System.out.println("Invoking the method " +joinPoint.getSignature() +" by LogExecutionTimeByMethod Advice"); 
     return joinPoint.proceed(); 
    } 


    /* 
    * Pointcut to match all the public methods that are defined under the Class marked with Annotation LogExecutionTime. 
    */ 
    @Pointcut("within(@LogExecutionTime *)") 
    public void beanAnnotatedWithMonitor() {} 

    @Pointcut("publicMethod() && beanAnnotatedWithMonitor()") 
    public void publicMethodInsideAClassMarkedWithAtMonitor() {} 

    /* 
    * Below Advice works but I need the LogExecutionTime annotation as an argument to below method. (similar to the advice "LogExecutionTimeByMethod" 
    * defined above) 
    */ 
    @Around("publicMethodInsideAClassMarkedWithAtMonitor()") 
    public Object LogExecutionTimeByClass(final ProceedingJoinPoint joinPoint) throws Throwable 
    { 
     System.out.println("Invoking the method " +joinPoint.getSignature() +" by LogExecutionTimeByClass Advice"); 
     //System.out.println("Invoked by " + annotation.value()); //Need the Annotation Variable here as well... 
     return joinPoint.proceed(); 
    } 

/* 
    */ 
} 

chú thích Class:

@LogExecutionTime(level="Class_Level_Invocation") 
public class Operator { 

    @LogExecutionTime(level="Method_Level_Invocation") 
    public void operate() throws InterruptedException { 
     Thread.sleep(1000); 
    } 

    public void operate1() throws InterruptedException { 
     Thread.sleep(1000); 
    } 
} 

Chương trình chi tiết:

public class AspectJMain { 
    public static void main(String[] args) throws InterruptedException { 
      Operator op = new Operator(); 
      op.operate(); 
      op.operate1(); 
     } 
} 

Đầu ra:

Invoking the method void Operator.operate() by LogExecutionTimeByMethod Advice 
Invoking the method void Operator.operate() by LogExecutionTimeByClass Advice 
Invoking the method void Operator.operate1() by LogExecutionTimeByClass Advice 

Xin lưu ý rằng việc sử dụng Spring không phải là một tùy chọn. Tôi phải sử dụng trình biên dịch AspectJ. Tôi đã biên dịch các lớp của mình và đóng gói chúng thành jar và sử dụng trình biên dịch ApsectJ để dệt khía cạnh bằng cách sử dụng lệnh dưới đây.

AJC -inpath core.jar -outjar .. \ lib \ core_woven.jar -1.5

Bất kỳ con trỏ sẽ là hữu ích.

Trả lời

12

Giải pháp thực sự khá đơn giản. Tôi viết mã của tôi theo kiểu AspectJ bản địa, tôi thích nó cho rõ ràng hơn. Bạn sẽ có thể dễ dàng điều chỉnh nó để @AspectJ chú thích phong cách:

public aspect LogTimeAspect { 
    pointcut publicMethod() : execution(public * *(..)); 

    before(LogExecutionTime logAnn) : publicMethod() && @annotation(logAnn) { 
     System.out.println(thisJoinPointStaticPart + " -> " + logAnn.level()); 
    } 

    before(LogExecutionTime logAnn) : publicMethod() && @within(logAnn) { 
     System.out.println(thisJoinPointStaticPart + " -> " + logAnn.level()); 
    } 
} 

Kết quả như sau:

execution(void Operator.operate()) -> Method_Level_Invocation 
execution(void Operator.operate()) -> Class_Level_Invocation 
execution(void Operator.operate1()) -> Class_Level_Invocation 

Như bạn thấy,

  • không có nhu cầu around() lời khuyên, before() là đủ trừ khi bạn muốn thao tác bất kỳ thông số nào hoặc chặn thực thi phương thức đã chụp,
  • bạn có thể liên kết các chú thích được đề cập qua thông tin @annotation() hoặc @within() đến các tham số được đặt tên nếu bạn chỉ sử dụng đúng cú pháp.

Tận hưởng!:-)


Cập nhật: Dưới đây là phiên bản @AspectJ của khía cạnh thuận tiện cho bạn và vì bạn dường như có vấn đề thích nghi với giải pháp của tôi từ cú pháp bản địa:

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 LogTimeAspect { 
    @Pointcut("execution(public * *(..))") 
    public void publicMethod() {} 

    @Around("publicMethod() && @annotation(logAnn)") 
    public Object LogExecutionTimeByMethod(ProceedingJoinPoint joinPoint, LogExecutionTime logAnn) throws Throwable { 
     System.out.println(joinPoint + " -> " + logAnn.level()); 
     return joinPoint.proceed(); 
    } 

    @Around("publicMethod() && @within(logAnn)") 
    public Object LogExecutionTimeByClass(ProceedingJoinPoint joinPoint, LogExecutionTime logAnn) throws Throwable { 
     System.out.println(joinPoint + " -> " + logAnn.level()); 
     return joinPoint.proceed(); 
    } 
} 

Kết quả sẽ được giống với phiên bản gốc của tôi.

+0

Cảm ơn. Hãy để tôi thử. Lý do cho xung quanh là để có được thời gian thực hiện của phương pháp. – param83

+0

Tôi đã thử nhưng không thể chuyển đối số chú thích qua bên trong nhưng bên dưới công cụ cắt điểm @Pointcut ("publicMethod() && beanAnnotatedWithMonitor() && @annotation (chú thích)") – param83

+0

Bạn thực sự không cần 'beanAnnotatedWithMonitor()', xem cập nhật của tôi ở trên. – kriegaex

Các vấn đề liên quan