diff --git a/spring-mvc-java/pom.xml b/spring-mvc-java/pom.xml
index 5875af5631..772bbbb219 100644
--- a/spring-mvc-java/pom.xml
+++ b/spring-mvc-java/pom.xml
@@ -38,6 +38,38 @@
runtime
+
+
+ org.springframework
+ spring-aop
+ ${org.springframework.version}
+
+
+
+ org.aspectj
+ aspectjrt
+ ${aspectj.version}
+
+
+
+ org.aspectj
+ aspectjweaver
+ ${aspectj.version}
+
+
+
+
+ org.slf4j
+ slf4j-api
+ ${org.slf4j.version}
+
+
+
+ org.slf4j
+ slf4j-log4j12
+ ${org.slf4j.version}
+
+
@@ -67,6 +99,13 @@
test
+
+ org.springframework
+ spring-test
+ ${org.springframework.version}
+ test
+
+
@@ -175,6 +214,8 @@
2.7
1.4.15
+
+ 1.8.7
\ No newline at end of file
diff --git a/spring-mvc-java/src/main/java/org/baeldung/aop/PerformanceAspect.java b/spring-mvc-java/src/main/java/org/baeldung/aop/PerformanceAspect.java
new file mode 100644
index 0000000000..12d6bc4e69
--- /dev/null
+++ b/spring-mvc-java/src/main/java/org/baeldung/aop/PerformanceAspect.java
@@ -0,0 +1,31 @@
+package org.baeldung.aop;
+
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.springframework.stereotype.Component;
+
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Logger;
+
+@Aspect
+@Component
+public class PerformanceAspect {
+
+ private static Logger logger = Logger.getLogger(PerformanceAspect.class.getName());
+
+ @Pointcut("within(@org.springframework.stereotype.Repository *)")
+ public void repositoryClassMethods() {};
+
+ @Around("repositoryClassMethods()")
+ public Object measureMethodExecutionTime(ProceedingJoinPoint pjp) throws Throwable {
+ long start = System.nanoTime();
+ Object retval = pjp.proceed();
+ long end = System.nanoTime();
+ String methodName = pjp.getSignature().getName();
+ logger.info("Execution of " + methodName + " took " + TimeUnit.NANOSECONDS.toMillis(end - start) + " ms");
+ return retval;
+ }
+
+}
diff --git a/spring-mvc-java/src/main/java/org/baeldung/dao/FooDao.java b/spring-mvc-java/src/main/java/org/baeldung/dao/FooDao.java
new file mode 100644
index 0000000000..fbd7f4c717
--- /dev/null
+++ b/spring-mvc-java/src/main/java/org/baeldung/dao/FooDao.java
@@ -0,0 +1,10 @@
+package org.baeldung.dao;
+
+import org.springframework.stereotype.Repository;
+
+@Repository
+public class FooDao {
+ public String findById(Long id) {
+ return "Bazz";
+ }
+}
diff --git a/spring-mvc-java/src/test/java/org/baeldung/aop/AopPerformanceTest.java b/spring-mvc-java/src/test/java/org/baeldung/aop/AopPerformanceTest.java
new file mode 100644
index 0000000000..82af95957a
--- /dev/null
+++ b/spring-mvc-java/src/test/java/org/baeldung/aop/AopPerformanceTest.java
@@ -0,0 +1,69 @@
+package org.baeldung.aop;
+
+import org.baeldung.config.TestConfig;
+import org.baeldung.dao.FooDao;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.AnnotationConfigContextLoader;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Handler;
+import java.util.logging.LogRecord;
+import java.util.logging.Logger;
+import java.util.regex.Pattern;
+
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.Matchers.hasSize;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = {TestConfig.class}, loader = AnnotationConfigContextLoader.class)
+public class AopPerformanceTest {
+
+ @Before
+ public void setUp() {
+ logEventHandler = new Handler() {
+ @Override
+ public void publish(LogRecord record) {
+ messages.add(record.getMessage());
+ }
+
+ @Override
+ public void flush() {
+ }
+
+ @Override
+ public void close() throws SecurityException {
+ }
+ };
+
+ messages = new ArrayList<>();
+ }
+
+ @Autowired
+ private FooDao dao;
+
+ private Handler logEventHandler;
+
+ private List messages;
+
+ @Test
+ public void givenPerformanceAspect_whenCallDaoMethod_thenPerformanceMeasurementAdviceIsCalled() {
+ Logger logger = Logger.getLogger(PerformanceAspect.class.getName());
+ logger.addHandler(logEventHandler);
+
+ final String entity = dao.findById(1L);
+ assertThat(entity, notNullValue());
+ assertThat(messages, hasSize(1));
+
+ String logMessage = messages.get(0);
+ Pattern pattern = Pattern.compile("Execution of findById took \\d+ ms");
+ assertTrue(pattern.matcher(logMessage).matches());
+ }
+}
diff --git a/spring-mvc-java/src/test/java/org/baeldung/config/TestConfig.java b/spring-mvc-java/src/test/java/org/baeldung/config/TestConfig.java
new file mode 100644
index 0000000000..60786a108c
--- /dev/null
+++ b/spring-mvc-java/src/test/java/org/baeldung/config/TestConfig.java
@@ -0,0 +1,11 @@
+package org.baeldung.config;
+
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
+
+@Configuration
+@ComponentScan(basePackages = {"org.baeldung.dao", "org.baeldung.aop"})
+@EnableAspectJAutoProxy
+public class TestConfig {
+}
diff --git a/spring-mvc-java/src/test/resources/log4j.properties b/spring-mvc-java/src/test/resources/log4j.properties
new file mode 100644
index 0000000000..6193d62fd8
--- /dev/null
+++ b/spring-mvc-java/src/test/resources/log4j.properties
@@ -0,0 +1,9 @@
+# Set root logger level to DEBUG and its only appender to A1.
+log4j.rootLogger=WARN, A1
+
+# A1 is set to be a ConsoleAppender.
+log4j.appender.A1=org.apache.log4j.ConsoleAppender
+
+# A1 uses PatternLayout.
+log4j.appender.A1.layout=org.apache.log4j.PatternLayout
+log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
\ No newline at end of file