2017-07-01 92 views
0

我已經寫了一個註釋(在spring引導應用程序中)並嘗試將其應用於Callablecall()方法,但它不起作用,但另一方面,當應用於正常的方法(請參閱下面的代碼),它的工作原理,這一直困擾着我,請你給我一些線索?非常感謝你。Java註釋在Callable上不起作用

這裏是我的代碼,

@Target(ElementType.METHOD) 
@Retention(RetentionPolicy.RUNTIME) 
public @interface LogExecutionTime { 
} 

@Aspect 
@Component 
public class LogExecutionTimeAspect { 

    private static final Logger logger = LoggerFactory.getLogger(LogExecutionTimeAspect.class); 

    @Around("@annotation(LogExecutionTime)") 
    public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable { 
     final long start = System.currentTimeMillis(); 
     final Object proceed = joinPoint.proceed(); 
     final long executionTime = System.currentTimeMillis() - start; 
     logger.info(joinPoint.getSignature() + " executed in " + executionTime + "ms"); 
     return proceed; 
    } 
} 


public class DummyCallable implements Callable<Integer> { 

    private Integer start, count; 

    DummyCallable() {} 

    DummyCallable(Integer start, Integer count) { 
     this.start = start; 
     this.count = count; 
    } 

    @LogExecutionTime // not working... 
    @Override 
    public Integer call() throws Exception { 
     Thread.sleep(start * 1000); 
     Integer sum = 0; 
     for (Integer i = start; i <= start + count; i++) { 
      sum += i; 
     } 
     return sum; 
    } 
} 



@LogExecutionTime // This will work... 
public List<Integer> getAllUserScores() { 
    Callable c1 = new DummyCallable(1, 100000); 
    Callable c2 = new DummyCallable(2, 100000); 
    Callable c3 = new DummyCallable(3, 100000); 
    // .... run them ... 
    return result; 
} 
+1

Spring使用代理,只有方法調用INTO對象被攔截,你在內部調用一個方法。 –

回答

0

通過@sbjavateam啓發,我意識到三件事,

  1. spring aop work only with object that are managed by spring container. To apply aspect for your class it should be a bean or component and instantiated by spring context.(好吧,這是從@ sbjavateam的答案被複制。)
  2. 根據前面的說法,Callable c1 = new DummyCallable(1, 100000);本質上是錯誤的,因爲我們必須從spring上下文創建DummyCallable(這樣bean纔會被正確地注入它的依賴),調用new不能勝任。
  3. DummyCallable類需要有一個原型範圍,以便它不是一個單例。單例作用域是Spring bean的默認作用域。因此,這個類必須有這個註釋:@Scope("prototype")

下面是我的修正,

@Component 
@Scope("prototype") 
public class DummyCallable implements Callable<Integer> {} 


private DummyCallable createDummyCallable(Integer start, Integer end) { 
     return context.getBean(DummyCallable.class, start, end); 
    } 

此外,你可能想這個配置,以及,

spring.aop.proxy-target-class=true 

最後但並非最不重要的,非常感謝你,@sbjavateam。

+0

一些說法,關於點2:你可以在沒有spring aop的情況下爲這個調用應用方面,你可以通過容器對託管bean應用ascpect,但是你需要用特定代理編譯你的項目。 AspectJ可以在編譯期間或在上傳時使用。 Spring aop支持aspectj,所以如果你使用代理spring aop編譯項目將支持這個調用/。 https://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html#aop-aj-ltw – xyz