2015-10-20 88 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

添加配置,我无法真正添加一切,因为它是一个非常大的应用程序的一部分 –