Javaは反射を利用して、どうやって指定された注釈を使うクラスを調べますか?


前言
最近空いていますが、自分でspringの注釈と同じような注釈を書いて使って、自分で注釈を書いた種類を見つけたいです。実現方法を紹介します。
声明の下のコードはspringのソースコードを見たことがないので、ほぼすべてネット上で探したブログで、整理しました。
コメントを定義
Controller.java

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Controller {

}
Request Mappingn.java

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestMapping {

 String value();

}
コメントを使う

@Controller
public class IndexController {

 @RequestMapping("/")
 public void index() {
 System.out.println("index method")
 }

 @RequestMapping("/about")
 public void about(String args) {
 System.out.println("about method")
 }

}
すべてのクラスをスキャンします。
以下のコードはネットブログからのものです。

/**
 *   package      Class
 *
 * @param packageName
 * @return
 */
public static List<Class<?>> getClasses(String packageName) {

 //    class    
 List<Class<?>> classes = new ArrayList<Class<?>>();
 //       
 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");
  //                        
  findAndAddClassesInPackageByFile(packageName, filePath, recursive, classes);
  } 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;
}
パッケージ名が入ると、自動的に次のクラスをスキャンします。
注を使ったクラスを探してください。

//    Controller    
private List<Class<?>> controllers;

public List<Class<?>> getControllers() {
 if (controllers == null) {
 controllers = new ArrayList<>();
 List<Class<?>> clsList = getAllClass();
 if (clsList != null && clsList.size() > 0) {
  for (Class<?> cls : clsList) {
  if (cls.getAnnotation(Controller.class) != null) {
   Map<Class<?>, Object> map = new HashMap<>();
   controllers.add(cls);
  }
  }
 }
 }
 return controllers;
}
Request Mappingを用いて注釈する方法を調べ,注入パラメータを調べた。

for (Class<?> cls : getControllers()) {
 Method[] methods = cls.getMethods();
 for (Method method : methods) {
 RequestMapping annotation = method.getAnnotation(RequestMapping.class);
 if (annotation != null) {
  String value = annotation.value();//  RequestMapping   value 
  if (value.equals("/about")) {//     /about,   ,   about(args)  
  method.invoke(cls.newInstance(), "args"); //            
  }
 }
 }
}
このようにして、javaプロジェクトの中で純粋なservletで書いたプロジェクトは自分の注釈マッピングルートを作ることができます。とても便利です。
締め括りをつける
以上はこの文章の全部の内容です。本文の内容は皆さんの学習や仕事に対して一定の参考となる学習価値を持っています。質問があれば、メッセージを書いて交流してください。ありがとうございます。