diff --git a/spring-boot-modules/spring-boot-libraries-2/pom.xml b/spring-boot-modules/spring-boot-libraries-2/pom.xml
index f62a341efc..79c090dde5 100644
--- a/spring-boot-modules/spring-boot-libraries-2/pom.xml
+++ b/spring-boot-modules/spring-boot-libraries-2/pom.xml
@@ -62,6 +62,16 @@
spqr
0.11.2
+
+ org.reflections
+ reflections
+ 0.10.2
+
+
+ org.jboss
+ jandex
+ 2.4.3.Final
+
@@ -92,6 +102,27 @@
+
+ org.jboss.jandex
+ jandex-maven-plugin
+ 1.2.3
+
+
+ compile
+ make-index
+
+ jandex
+
+
+
+
+ ${project.build.outputDirectory}
+
+
+
+
+
+
diff --git a/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/SampleAnnotatedClass.java b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/SampleAnnotatedClass.java
new file mode 100644
index 0000000000..64849d6a3a
--- /dev/null
+++ b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/SampleAnnotatedClass.java
@@ -0,0 +1,14 @@
+package com.baeldung.annotation.scanner;
+
+@SampleAnnotation(name = "SampleAnnotatedClass")
+public class SampleAnnotatedClass {
+
+ @SampleAnnotation(name = "annotatedMethod")
+ public void annotatedMethod() {
+ //Do something
+ }
+
+ public void notAnnotatedMethod() {
+ //Do something
+ }
+}
diff --git a/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/SampleAnnotation.java b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/SampleAnnotation.java
new file mode 100644
index 0000000000..212e12e910
--- /dev/null
+++ b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/SampleAnnotation.java
@@ -0,0 +1,14 @@
+package com.baeldung.annotation.scanner;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+@Target({ METHOD, TYPE })
+@Retention(RUNTIME)
+public @interface SampleAnnotation {
+ String name();
+}
diff --git a/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/SampleAnnotationScanner.java b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/SampleAnnotationScanner.java
new file mode 100644
index 0000000000..5cc9a2e8b3
--- /dev/null
+++ b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/SampleAnnotationScanner.java
@@ -0,0 +1,13 @@
+package com.baeldung.annotation.scanner;
+
+import java.util.List;
+
+public interface SampleAnnotationScanner {
+ List scanAnnotatedMethods();
+
+ List scanAnnotatedClasses();
+
+ boolean supportsMethodScan();
+
+ boolean supportsClassScan();
+}
diff --git a/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/ScanNotSupportedException.java b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/ScanNotSupportedException.java
new file mode 100644
index 0000000000..1566dc3fad
--- /dev/null
+++ b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/ScanNotSupportedException.java
@@ -0,0 +1,4 @@
+package com.baeldung.annotation.scanner;
+
+public class ScanNotSupportedException extends RuntimeException{
+}
diff --git a/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/UnexpectedScanException.java b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/UnexpectedScanException.java
new file mode 100644
index 0000000000..bd7c129bfd
--- /dev/null
+++ b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/UnexpectedScanException.java
@@ -0,0 +1,7 @@
+package com.baeldung.annotation.scanner;
+
+public class UnexpectedScanException extends RuntimeException {
+ public UnexpectedScanException(Throwable ex) {
+ super(ex);
+ }
+}
diff --git a/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/jandexlib/JandexScannerService.java b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/jandexlib/JandexScannerService.java
new file mode 100644
index 0000000000..fc10db223e
--- /dev/null
+++ b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/jandexlib/JandexScannerService.java
@@ -0,0 +1,76 @@
+package com.baeldung.annotation.scanner.jandexlib;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.jboss.jandex.AnnotationInstance;
+import org.jboss.jandex.AnnotationTarget;
+import org.jboss.jandex.DotName;
+import org.jboss.jandex.Index;
+import org.jboss.jandex.IndexReader;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.core.io.Resource;
+import org.springframework.stereotype.Service;
+
+import com.baeldung.annotation.scanner.SampleAnnotationScanner;
+import com.baeldung.annotation.scanner.UnexpectedScanException;
+
+@Service
+public class JandexScannerService implements SampleAnnotationScanner {
+ @Value("classpath:META-INF/jandex.idx")
+ private Resource appFile;
+
+ @Override
+ public List scanAnnotatedMethods() {
+ try {
+ final IndexReader reader = new IndexReader(appFile.getInputStream());
+ Index jandexFile = reader.read();
+ final List appAnnotationList = jandexFile.getAnnotations(DotName.createSimple("com.baeldung.annotation.scanner.SampleAnnotation"));
+ List annotatedMethods = new ArrayList<>();
+ for (AnnotationInstance annotationInstance : appAnnotationList) {
+ if (annotationInstance.target()
+ .kind() == AnnotationTarget.Kind.METHOD) {
+ annotatedMethods.add(annotationInstance.value("name")
+ .value()
+ .toString());
+ }
+ }
+ return Collections.unmodifiableList(annotatedMethods);
+ } catch (IOException e) {
+ throw new UnexpectedScanException(e);
+ }
+ }
+
+ @Override
+ public List scanAnnotatedClasses() {
+ try {
+ final IndexReader reader = new IndexReader(appFile.getInputStream());
+ Index jandexFile = reader.read();
+ final List appAnnotationList = jandexFile.getAnnotations(DotName.createSimple("com.baeldung.annotation.scanner.SampleAnnotation"));
+ List annotatedClasses = new ArrayList<>();
+ for (AnnotationInstance annotationInstance : appAnnotationList) {
+ if (annotationInstance.target()
+ .kind() == AnnotationTarget.Kind.CLASS) {
+ annotatedClasses.add(annotationInstance.value("name")
+ .value()
+ .toString());
+ }
+ }
+ return Collections.unmodifiableList(annotatedClasses);
+ } catch (IOException e) {
+ throw new UnexpectedScanException(e);
+ }
+ }
+
+ @Override
+ public boolean supportsMethodScan() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsClassScan() {
+ return true;
+ }
+}
diff --git a/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/javareflectionlib/JavaReflectionsScannerService.java b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/javareflectionlib/JavaReflectionsScannerService.java
new file mode 100644
index 0000000000..2833bb1326
--- /dev/null
+++ b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/javareflectionlib/JavaReflectionsScannerService.java
@@ -0,0 +1,58 @@
+package com.baeldung.annotation.scanner.javareflectionlib;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.springframework.stereotype.Service;
+
+import com.baeldung.annotation.scanner.SampleAnnotation;
+import com.baeldung.annotation.scanner.SampleAnnotationScanner;
+import com.baeldung.annotation.scanner.UnexpectedScanException;
+
+@Service
+public class JavaReflectionsScannerService implements SampleAnnotationScanner {
+ @Override
+ public List scanAnnotatedMethods() {
+ try {
+ Class> clazz = ClassLoader.getSystemClassLoader()
+ .loadClass("com.baeldung.annotation.scanner.SampleAnnotatedClass");
+ Method[] methods = clazz.getMethods();
+ List annotatedMethods = new ArrayList<>();
+ for (Method method : methods) {
+ SampleAnnotation annotation = method.getAnnotation(SampleAnnotation.class);
+ if (annotation != null) {
+ annotatedMethods.add(annotation.name());
+ }
+ }
+ return Collections.unmodifiableList(annotatedMethods);
+ } catch (ClassNotFoundException e) {
+ throw new UnexpectedScanException(e);
+ }
+ }
+
+ @Override
+ public List scanAnnotatedClasses() {
+ try {
+ Class> clazz = ClassLoader.getSystemClassLoader()
+ .loadClass("com.baeldung.annotation.scanner.SampleAnnotatedClass");
+ SampleAnnotation classAnnotation = clazz.getAnnotation(SampleAnnotation.class);
+ List annotatedClasses = new ArrayList<>();
+ annotatedClasses.add(classAnnotation.name());
+ return Collections.unmodifiableList(annotatedClasses);
+ } catch (ClassNotFoundException e) {
+ throw new UnexpectedScanException(e);
+ }
+ }
+
+ @Override
+ public boolean supportsMethodScan() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsClassScan() {
+ return true;
+ }
+}
diff --git a/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/reflectionslib/ReflectionsScannerService.java b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/reflectionslib/ReflectionsScannerService.java
new file mode 100644
index 0000000000..82a10e21aa
--- /dev/null
+++ b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/reflectionslib/ReflectionsScannerService.java
@@ -0,0 +1,45 @@
+package com.baeldung.annotation.scanner.reflectionslib;
+
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.reflections.Reflections;
+import org.springframework.stereotype.Service;
+
+import com.baeldung.annotation.scanner.SampleAnnotation;
+import com.baeldung.annotation.scanner.SampleAnnotationScanner;
+
+@Service
+public class ReflectionsScannerService implements SampleAnnotationScanner {
+ @Override
+ public List scanAnnotatedMethods() {
+ Reflections reflections = new Reflections("com.baeldung.annotation.scanner");
+ Set methods = reflections.getMethodsAnnotatedWith(SampleAnnotation.class);
+ return methods.stream()
+ .map(method -> method.getAnnotation(SampleAnnotation.class)
+ .name())
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public List scanAnnotatedClasses() {
+ Reflections reflections = new Reflections("com.baeldung.annotation.scanner");
+ Set> types = reflections.getTypesAnnotatedWith(SampleAnnotation.class);
+ return types.stream()
+ .map(clazz -> clazz.getAnnotation(SampleAnnotation.class)
+ .name())
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public boolean supportsMethodScan() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsClassScan() {
+ return true;
+ }
+}
diff --git a/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/springcontextlib/SpringBeanAnnotationScannerService.java b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/springcontextlib/SpringBeanAnnotationScannerService.java
new file mode 100644
index 0000000000..cd31ae686e
--- /dev/null
+++ b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/springcontextlib/SpringBeanAnnotationScannerService.java
@@ -0,0 +1,52 @@
+package com.baeldung.annotation.scanner.springcontextlib;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
+import org.springframework.core.type.filter.AnnotationTypeFilter;
+import org.springframework.stereotype.Service;
+
+import com.baeldung.annotation.scanner.SampleAnnotation;
+import com.baeldung.annotation.scanner.SampleAnnotationScanner;
+import com.baeldung.annotation.scanner.ScanNotSupportedException;
+
+@Service
+public class SpringBeanAnnotationScannerService implements SampleAnnotationScanner {
+ @Override
+ public List scanAnnotatedMethods() {
+ throw new ScanNotSupportedException();
+ }
+
+ @Override
+ public List scanAnnotatedClasses() {
+ ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
+ provider.addIncludeFilter(new AnnotationTypeFilter(SampleAnnotation.class));
+ Set beanDefs = provider.findCandidateComponents("com.baeldung.annotation.scanner");
+ List annotatedBeans = new ArrayList<>();
+ for (BeanDefinition bd : beanDefs) {
+ if (bd instanceof AnnotatedBeanDefinition) {
+ Map annotAttributeMap = ((AnnotatedBeanDefinition) bd).getMetadata()
+ .getAnnotationAttributes(SampleAnnotation.class.getCanonicalName());
+ annotatedBeans.add(annotAttributeMap.get("name")
+ .toString());
+ }
+ }
+ return Collections.unmodifiableList(annotatedBeans);
+ }
+
+ @Override
+ public boolean supportsMethodScan() {
+ return false;
+ }
+
+ @Override
+ public boolean supportsClassScan() {
+ return true;
+ }
+}
diff --git a/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/springcorelib/SpringCoreAnnotationScannerService.java b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/springcorelib/SpringCoreAnnotationScannerService.java
new file mode 100644
index 0000000000..f3421fe46d
--- /dev/null
+++ b/spring-boot-modules/spring-boot-libraries-2/src/main/java/com/baeldung/annotation/scanner/springcorelib/SpringCoreAnnotationScannerService.java
@@ -0,0 +1,42 @@
+package com.baeldung.annotation.scanner.springcorelib;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.springframework.core.annotation.AnnotationUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.util.ClassUtils;
+
+import com.baeldung.annotation.scanner.SampleAnnotationScanner;
+import com.baeldung.annotation.scanner.SampleAnnotatedClass;
+import com.baeldung.annotation.scanner.SampleAnnotation;
+import com.baeldung.annotation.scanner.ScanNotSupportedException;
+
+@Service
+public class SpringCoreAnnotationScannerService implements SampleAnnotationScanner {
+ @Override
+ public List scanAnnotatedMethods() {
+ final Class> userClass = ClassUtils.getUserClass(SampleAnnotatedClass.class);
+ return Arrays.stream(userClass.getMethods())
+ .filter(method -> AnnotationUtils.getAnnotation(method, SampleAnnotation.class) != null)
+ .map(method -> method.getAnnotation(SampleAnnotation.class)
+ .name())
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public List scanAnnotatedClasses() {
+ throw new ScanNotSupportedException();
+ }
+
+ @Override
+ public boolean supportsMethodScan() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsClassScan() {
+ return false;
+ }
+}
diff --git a/spring-boot-modules/spring-boot-libraries-2/src/test/java/com/baeldung/annotation/scanner/SampleAnnotationScannerUnitTest.java b/spring-boot-modules/spring-boot-libraries-2/src/test/java/com/baeldung/annotation/scanner/SampleAnnotationScannerUnitTest.java
new file mode 100644
index 0000000000..80eca2b4c5
--- /dev/null
+++ b/spring-boot-modules/spring-boot-libraries-2/src/test/java/com/baeldung/annotation/scanner/SampleAnnotationScannerUnitTest.java
@@ -0,0 +1,47 @@
+package com.baeldung.annotation.scanner;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import static org.junit.Assert.*;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class SampleAnnotationScannerUnitTest {
+ @Autowired
+ private List scannerList;
+
+ @Test
+ public void givenPackage_whenScanAnnotatedClasses_thenAnnotationValues() {
+ final List annotatedClasses = scannerList.stream()
+ .filter(SampleAnnotationScanner::supportsClassScan)
+ .map(SampleAnnotationScanner::scanAnnotatedClasses)
+ .flatMap(Collection::stream)
+ .collect(Collectors.toList());
+
+ assertNotNull(annotatedClasses);
+ assertEquals(4, annotatedClasses.size());
+ annotatedClasses.forEach(annotValue -> assertEquals("SampleAnnotatedClass", annotValue));
+ }
+
+ @Test
+ public void givenPackage_whenScanAnnotatedMethods_thenAnnotationValues() {
+ final List annotatedMethods = scannerList.stream()
+ .filter(SampleAnnotationScanner::supportsMethodScan)
+ .map(SampleAnnotationScanner::scanAnnotatedMethods)
+ .flatMap(Collection::stream)
+ .collect(Collectors.toList());
+
+ assertNotNull(annotatedMethods);
+ assertEquals(3, annotatedMethods.size());
+ annotatedMethods.forEach(annotValue -> assertEquals("annotatedMethod", annotValue));
+ }
+
+}