2015-10-20 90 views
1

我想通過完成一個記錄函數執行時間的非常簡單的函數來了解Aspects和自定義註釋。我有以下方面和註釋和註釋函數,但是當我調用註釋函數時,方面代碼不會被調用。我如何將註釋與該方面聯繫起來?如何獲得註釋功能點火?

另外我試着用@Aspect聲明文件的一個方面不是類,並且刪除'@annotation(Benchmark)',並且不試圖傳入註釋,但它似乎永遠不會工作。

@Benchmark譯註:

看點

package net.tia.util.aspects; 

import org.apache.log4j.Logger; 
import org.aspectj.lang.ProceedingJoinPoint; 
import org.aspectj.lang.annotation.Around; 
import org.aspectj.lang.annotation.Aspect; 
import org.springframework.stereotype.Component; 

import java.text.MessageFormat; 


@Component 
@Aspect 
public class BenchmarkAspect { 
    private static final Logger logger = Logger.getLogger(BenchmarkAspect.class); 

    @Around(value = "@annotation(Benchmark)") 
    public Object benchmarkFunctionExecution(final ProceedingJoinPoint joinPoint, final Benchmark benchmark) throws Throwable { 
     final long startMillis = System.currentTimeMillis(); 

     Object retVal = null; 
     try { 
      System.out.println("Starting timed operation"); 
      retVal = joinPoint.proceed(); 
      return retVal; 
     } finally { 
      final long duration = System.currentTimeMillis() - startMillis; 
      String logMessage = MessageFormat.format("{0} Call to {1} took {2}ms", annotation.description(), joinPoint.getSignature(), duration); 
      if(annotation.logReturnValue() && (retVal != null)){ 
       logMessage += " Returned: " + retVal.toString(); 
      } 
      logger.debug(logMessage); 
     } 
    } 
} 

調用上我已經在一個已經存在的@Service bean,同時從端點稱爲聲明的隨機函數。

@Benchmark(logReturnValue = true, description = "Overall Time") 
public String dummyFunc() { 
    log.info("Attempting to call aspect"); 
{ 

配置

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:aop="http://www.springframework.org/schema/aop" 
    xmlns:context="http://www.springframework.org/schema/context" 
    xmlns:util="http://www.springframework.org/schema/util" 
    xmlns:mvc="http://www.springframework.org/schema/mvc" 
    xmlns:cache="http://www.springframework.org/schema/cache" 
    xsi:schemaLocation=" 
     http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 
     http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd 
     http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd 
     http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd 
     http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd 
     http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd 
    " 
> 

    <!-- enable custom annotations for benchmarking --> 
    <aop:aspectj-autoproxy/> 
    <!-- Annotation-driven non-MVC classes --> 
    <context:annotation-config/> 
    <context:component-scan base-package="net.tia.extensions,net.tia.sec" /> 
    <beans profile="ldap"> 
     <bean id="AuthenticationProvider" class="net.tia.authentication.LdapAuthenticationProviderImpl"> 
      <property name="userDetailsService" ref="localUserDetailsService"/> 
      <property name="authenticator"> 
       <bean class="net.tia.authentication.LdapAuthenticatorImpl"> 
        <property name="pricipalPattern"> 
         <value>tia\#login#</value> 
        </property> 
        <property name="securityContextSource"> 
         <bean class="org.springframework.security.ldap.DefaultSpringSecurityContextSource"> 
          <constructor-arg value="ldap://127.0.0.1:452/"/> 
         </bean> 
        </property> 
       </bean> 
      </property> 
     </bean> 
    </beans> 

    <beans profile="altAuth"> 
     <bean id="siteAuthenticationProvider" class="net.tia.authentication.siteAuthenticationProviderImpl"> 
      <property name="userDetailsService" ref="localUserDetailsService"/> 
     </bean> 

     <bean id="singleSignOnIdentityDriver" class="net.tia.authentication.siteIdentityDriver"/> 
    </beans> 

</beans> 
+0

請告訴我們您的配置和採樣方法調用。 –

+0

啊等待它可能是配置,我還以爲系統已經有它啓用,因爲它有 \t' \t \t \t \t < - - > \t' 但這可能並不適用於我在做什麼。 –

+0

使用''更新了我的配置,但仍然無效。由於這是在一個大型項目中,我會在配置方面進行一些嘗試,但是對於'@ Around',我的語法是否正確?我看到人們說了很多不同的方式來做這個 –

回答

1

是我的語法正確的@Around

語法在documentation中定義。

你提供

execution(@net.tia.util.aspects.Benchmark * *(..)), && @annotation(Benchmark) 

其一,,是無效的。其次,execution是不必要的。 Spring AOP切入點只能匹配方法調用,而您似乎想要所有方法(public真的),所以@annotation的使用等同於您嘗試使用的execution

既然你也想用註釋中的連接點,所有你需要的是

@Around(value = "@annotation(annotation)") 

,其中括號內的annotation指的是你的方法參數。

這裏有一個完整的例子

@ComponentScan 
@Configuration 
@EnableAspectJAutoProxy(proxyTargetClass = true) 
public class Sample { 
    public static void main(String[] args) throws Exception { 
     AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Sample.class); 
     ctx.getBean(Foo.class).dummyFunc(); 
    } 
} 

@Component 
class Foo { 
    private static final Logger logger = LoggerFactory.getLogger(Foo.class); 

    @Benchmark 
    public String dummyFunc() { 
     logger.info("real method"); 
     return "sads"; 
    } 
} 

@Component 
@Aspect 
class BenchmarkAspect { 
    private static final Logger logger = LoggerFactory.getLogger(BenchmarkAspect.class); 

    @Around(value = "@annotation(benchmark)") 
    public Object benchmarkFunctionExecution(final ProceedingJoinPoint joinPoint, final Benchmark benchmark) throws Throwable { 
     System.out.println("intercepted"); 
     return joinPoint.proceed(); 
    } 
} 

@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.METHOD) 
@interface Benchmark { 
} 
+0

啊,我讀了更多,並看到,我試着這個'@Around(value =「@annotation(benchmark)」)'後變更變量名稱匹配,它仍然沒有不會被拿起來。我將更多地使用配置。這裏有很多移動部件,我試圖縮小在哪裏關注。 –

+0

用你的配置,假設你正確加載了它,並且我做了一堆其他的假設(如果你給出了一個完整的例子,我不會需要),這個工作正常。 –

+0

添加配置,我無法真正添加一切,因爲它是一個非常大的應用程序的一部分 –