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:
org.springframework spring-context 4.0.2.RELEASE org.reflections reflections 0.9.9-RC1 junit junit 4.8.2 log4j log4j 1.2.16
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 {
/**
*
*
* Scan class with specified annotation under specific packages, using util from spring.
*
*
* Sub package & inner class will be included.
*
*
* @param pkgArray
* an array of package path,
* @param annoClazzArray
* an array of annotation class,
* @return
*/
public static Set 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 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;
}
/**
*
* Scan class with specified annotation under a specific package, using a lib called "reflections".
*
*
* Sub package & inner class will be included.
*
*
* This method is deprecated, use getBeanSetWithAnno() instead.
*
*
* @param pkg
* package path
* @param annoClazz
* annotation class
* @return a set of class, or null if error occur,
*/
@Deprecated
public static Set> getClazzSetWithAnno(String pkg, Class extends Annotation> annoClazz) {
// get class set
Set> clazzSet = new Reflections(pkg).getTypesAnnotatedWith(annoClazz);
// get class set that with a specific annotation
Set> clazzWithAnnoSet = new HashSet>();
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 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 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> 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");
}
}