The following example is a way to measure the execution time for methods using Spring Aspect Oriented Programming (AOP).
First we need to create a new annotation:
Then we can create our aspect:
Now you can use the @ProfileExecution to annotate any public method on a bean managed by spring container to get profile information on logger:
First we need to create a new annotation:
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Inherited
@Documented
public @interface ProfileExecution
{
}
Then we can create our aspect:
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StopWatch;
@Aspect
public class ProfileExecutionAspect {
private static final Logger logger = LoggerFactory.getLogger(ProfileExecutionAspect.class);
@Pointcut(value="execution(public * *(..))")
public void anyPublicMethod() { }
@Around("anyPublicMethod() && @annotation(ProfileExecution)")
public void profileExecuteMethod(ProceedingJoinPoint jointPoint) throws Throwable {
Signature signature = jointPoint.getSignature();
String methodName = signature.toShortString();
StopWatch stopWatch = new StopWatch(ProfileExecutionAspect.class.getName());
stopWatch.start(methodName);
jointPoint.proceed();
stopWatch.stop();
logger.info(stopWatch.prettyPrint());
}
}
We also need to annotate our configuration file with @EnableAspectJAutoProxy and create a @Bean of our aspect type ProfileExecutionAspect. import org.springframework.context.annotation.*;
@Configuration
@ComponentScan
@EnableAspectJAutoProxy
public class Application {
@Bean
public ProfileExecutionAspect profileExecutionAspect() {
return new ProfileExecutionAspect();
}
}
I know that some people will argue that its better to use spring xml configuration with aop but personally i prefer to use annotations.Now you can use the @ProfileExecution to annotate any public method on a bean managed by spring container to get profile information on logger:
21:15:39.811 [main] INFO test.ProfileExecutionAspect - StopWatch 'test.ProfileExecutionAspect': running time (millis) = 10 ----------------------------------------- ms % Task name ----------------------------------------- 00010 100% TestClass.testMethod()For this sample to run you can use the following dependencies on your maven pom.xml file:
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.1.6.RELEASE</version> <exclusions> <exclusion> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>4.1.6.RELEASE</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.1.3</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>1.7.12</version> </dependency> </dependencies>
this aspect (ProfileExecutionAspect) is not working for all the types, it will fail for all the methods that return types with not null support (for example: public boolean hello()).
ReplyDeleteThe aspect should return always a result:
Object result = jointPoint.proceed();
Anyway is a very good example.