java取得パッケージの下で指定された注釈のクラス解析
方案一:reflectionsフレームを採用する(このフレームはcomple.google.guavaに依存する)
1、reflectionsフレームアドレス:https://github.com/ronmamo/reflections
2、プロジェクト依存
1、実現コード
1、reflectionsフレームアドレス:https://github.com/ronmamo/reflections
2、プロジェクト依存
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.9.11</version>
</dependency>
<dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId>
<version>21.0</version>
</dependency>
3、実現コード
//
Reflections f = new Reflections("com.ggband.netty.execute.command");
//
Set<Class<?>> set = f.getTypesAnnotatedWith(Cmd.class);
方案二:Class Loaderスキャンを採用する1、実現コード
package com.ggband.netty;
import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
public class Scanner {
/**
* package Class
*
* @param packageName
* @return
*/
public Set<Class<?>> getClasses(String packageName) throws Exception {
// class
//List<Class<?>> classes = new ArrayList<Class<?>>();
Set<Class<?>> classes = new HashSet<>();
//
boolean recursive = true;
//
String packageDirName = packageName.replace('.', '/');
// things
Enumeration<URL> dirs;
try {
dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
//
while (dirs.hasMoreElements()) {
//
URL url = dirs.nextElement();
//
String protocol = url.getProtocol();
//
if ("file".equals(protocol)) {
//
String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
//
addClass(classes, filePath, packageName);
} else if ("jar".equals(protocol)) {
// jar
// JarFile
JarFile jar;
try {
// jar
jar = ((JarURLConnection) url.openConnection()).getJarFile();
// jar
Enumeration<JarEntry> entries = jar.entries();
//
while (entries.hasMoreElements()) {
// jar jar META-INF
JarEntry entry = entries.nextElement();
String name = entry.getName();
// /
if (name.charAt(0) == '/') {
//
name = name.substring(1);
}
//
if (name.startsWith(packageDirName)) {
int idx = name.lastIndexOf('/');
// "/"
if (idx != -1) {
// "/" "."
packageName = name.substring(0, idx).replace('/', '.');
}
//
if ((idx != -1) || recursive) {
// .class
if (name.endsWith(".class") && !entry.isDirectory()) {
// ".class"
String className = name.substring(packageName.length() + 1, name.length() - 6);
try {
// classes
classes.add(Class.forName(packageName + '.' + className));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
return classes;
}
public void addClass(Set<Class<?>> classes, String filePath, String packageName) throws Exception {
File[] files = new File(filePath).listFiles(file -> (file.isFile() && file.getName().endsWith(".class")) || file.isDirectory());
assert files != null;
for (File file : files) {
String fileName = file.getName();
if (file.isFile()) {
String classsName = fileName.substring(0, fileName.lastIndexOf("."));
if (!packageName.isEmpty()) {
classsName = packageName + "." + classsName;
}
doAddClass(classes, classsName);
}
}
}
public void doAddClass(Set<Class<?>> classes, final String classsName) throws Exception {
ClassLoader classLoader = new ClassLoader() {
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
return super.loadClass(name);
}
};
classes.add(classLoader.loadClass(classsName));
}
public <A extends Annotation> Set<Class<?>> getAnnotationClasses(String packageName, Class<A> annotationClass) throws Exception {
// annotationClass
Set<Class<?>> controllers = new HashSet<>();
Set<Class<?>> clsList = getClasses(packageName);
if (clsList != null && clsList.size() > 0) {
for (Class<?> cls : clsList) {
if (cls.getAnnotation(annotationClass) != null) {
controllers.add(cls);
}
}
}
return controllers;
}
}
2、使用:
Set<Class<?>> set = new Scanner().getAnnotationClasses("com.ggband.netty.execute.command", Cmd.class);
拡充:今では自分の業務が実現できます。例えば、comp.gg band.netty.execute.com andに包まれてCmdに注釈されたクラスは、Cmd注釈valueと注釈されたクラスの実例があります。
Map<String, Command> beanContainer = new HashMap<>();
try {
//@1 reflections ( com.google.guava)
// Reflections f = new Reflections("com.ggband.netty.execute.command");
// Set<Class<?>> set = f.getTypesAnnotatedWith(Cmd.class);
//@2 ClassLoader
Set<Class<?>> set = new Scanner().getAnnotationClasses("com.ggband.netty.execute.command", Cmd.class);
for (Class<?> c : set) {
Object bean = c.newInstance();
Cmd annotation = c.getAnnotation(Cmd.class);
beanContainer.put(Arrays.toString(annotation.value()), (Command) bean);
}
} catch (Exception e) {
e.printStackTrace();
}
以上が本文の全部です。皆さんの勉強に役に立つように、私たちを応援してください。