Scan classes with specified annotation under specified package
程序员文章站
2022-06-05 18:21:54
...
Scan classes with specified annotation under specified package.
steps:
* define annotation
* use annotation on class
* get class set with specified annotations under specified packages,
2 approach:
* spring (preferred)
use util class from spring:
ClassPathScanningCandidateComponentProvider
* reflections lib
this lib provide class/methods to do this,
but it's not as good as spring,
*
* iterate the class set, read annotation, take actions as need,
*
maven:
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.0.2.RELEASE</version> </dependency> <dependency> <groupId>org.reflections</groupId> <artifactId>reflections</artifactId> <version>0.9.9-RC1</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.8.2</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.16</version> </dependency>
Util class:
package eric.j2se.anno; import java.lang.annotation.Annotation; import java.util.HashSet; import java.util.Set; import org.reflections.Reflections; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; import org.springframework.core.type.filter.AnnotationTypeFilter; /** * Util to get classes according to annotation on class in a specified package. * * @author eric * @date Aug 5, 2014 12:36:42 PM */ public class PkgAnnoUtil { /** * * <p> * Scan class with specified annotation under specific packages, using util from spring. * </p> * <p> * Sub package & inner class will be included. * </p> * * @param pkgArray * an array of package path, * @param annoClazzArray * an array of annotation class, * @return */ public static Set<BeanDefinition> getBeanSetWithAnno(String pkgArray[], Class<? extends Annotation>[] annoClazzArray) { // prepare scanner, with each annotation, ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(true); for (Class<? extends Annotation> annoclazz : annoClazzArray) { scanner.addIncludeFilter(new AnnotationTypeFilter(annoclazz)); } Set<BeanDefinition> beanSet = null; // search with each package, and combine search result, for (String pkg : pkgArray) { if (beanSet == null) { beanSet = scanner.findCandidateComponents(pkg); } else { beanSet.addAll(scanner.findCandidateComponents(pkg)); } } return beanSet; } /** * <p> * Scan class with specified annotation under a specific package, using a lib called "reflections". * </p> * <p> * Sub package & inner class will be included. * </p> * <p> * This method is deprecated, use getBeanSetWithAnno() instead. * </p> * * @param pkg * package path * @param annoClazz * annotation class * @return a set of class, or null if error occur, */ @Deprecated public static Set<Class<? extends Object>> getClazzSetWithAnno(String pkg, Class<? extends Annotation> annoClazz) { // get class set Set<Class<? extends Object>> clazzSet = new Reflections(pkg).getTypesAnnotatedWith(annoClazz); // get class set that with a specific annotation Set<Class<? extends Object>> clazzWithAnnoSet = new HashSet<Class<? extends Object>>(); for (Class<? extends Object> clazz : clazzSet) { if (clazz.getAnnotation(annoClazz) != null) { clazzWithAnnoSet.add(clazz); } } return clazzWithAnnoSet; } }
junit test:
package eric.j2se.anno; import java.lang.reflect.Method; import java.util.Set; import junit.framework.TestCase; import org.junit.Test; import org.springframework.beans.factory.config.BeanDefinition; public class PkgAnnoUtilTest extends TestCase { private Class<SimpleAnno> annoClazz = SimpleAnno.class; // annotation to filter class, private String pkg = "eric.j2se.anno.annopkg"; // package name to be search, private String methodName = "takeAction"; // name of method to execute, private int annotatedClassCount = 4; // count of class that is annotated, /** * test - getBeanSetWithAnno(), */ @Test @SuppressWarnings("unchecked") public void testGetBeanSetWithAnno() { System.out.println("------ annotation scan - spring - start ------"); // get classes with in package, and has specified annotation, Set<BeanDefinition> beanWithAnnoSet = PkgAnnoUtil.getBeanSetWithAnno(new String[] { pkg }, new Class[] { annoClazz }); assertEquals(beanWithAnnoSet.size(), annotatedClassCount); try { // execute a specific method, for (BeanDefinition bean : beanWithAnnoSet) { Class<? extends Object> clazz = Class.forName(bean.getBeanClassName()); Method md = clazz.getMethod(methodName); if (md != null) { md.invoke(clazz.newInstance()); } } } catch (Exception e) { e.printStackTrace(); } System.out.println("------ annotation scan - spring - end ------\n"); } /** * test - getClazzSetWithAnnoTest(), */ @SuppressWarnings("deprecation") @Test public void testGetClazzSetWithAnno() { System.out.println("------ annotation scan - reflections lib - start ------"); // get classes with in package, and has specified annotation, Set<Class<? extends Object>> clazzWithAnnoSet = PkgAnnoUtil.getClazzSetWithAnno(pkg, annoClazz); assertEquals(clazzWithAnnoSet.size(), annotatedClassCount); try { // execute a specific method, for (Class<? extends Object> clazz : clazzWithAnnoSet) { Method md = clazz.getMethod(methodName); if (md != null) { md.invoke(clazz.newInstance()); } } } catch (Exception e) { e.printStackTrace(); } System.out.println("------ annotation scan - reflections lib - end ------\n"); } }