如何让Aspect为注释函数启动?

时间:2015-10-20 03:09:45

标签: java annotations aop aspectj spring-aop

我试图通过完成一个记录函数执行时间的非常简单的函数来学习Aspects和自定义注释。我有以下方面和注释和注释函数,但是当我调用带注释的函数时,方法代码不会被调用。如何将注释与方面联系起来?

此外,我尝试将文件声明为一个方面而不是带有@Aspect的类,并且还删除了'@annotation(Benchmark)'并且没有尝试传入注释但它似乎永远不会起作用。

@Benchmark Annotation:

package net.tia.util.aspects;

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

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Benchmark {
    public boolean logReturnValue() default false;
    public String description() default "";
}

方面

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>

1 个答案:

答案 0 :(得分: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 {
}