`

Scan classes with specified annotation under specified package

    博客分类:
  • J2SE
 
阅读更多

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");
	}
}

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics