>  기사  >  Java  >  Java가 리플렉션을 사용하여 지정된 주석을 사용하여 클래스를 찾는 방법에 대한 자세한 설명

Java가 리플렉션을 사용하여 지정된 주석을 사용하여 클래스를 찾는 방법에 대한 자세한 설명

黄舟
黄舟원래의
2017-09-30 10:24:161891검색

이 글에서는 Java가 리플렉션을 사용하여 지정된 주석을 사용하는 클래스를 찾는 방법에 대한 관련 정보를 주로 소개합니다. 샘플 코드를 통해 자세히 소개합니다. 공부나 업무에 필요한 모든 사람에게 학습 가치가 있습니다. 아래 편집자와 함께.

머리말

저는 요즘 시간이 좀 있어서 봄에 썼던 Annotation과 비슷한 Annotation을 쓰고 싶어요. 그럼 제가 쓴 Annotation을 활용하는 클래스를 찾아보고 싶습니다

. 다음 코드는 Spring 소스 코드를 보지 않고 작성되었습니다. 이는 기본적으로 온라인에서 찾은 블로그에서 컴파일된 것입니다.

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

}

주석 사용

@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(&#39;.&#39;, &#39;/&#39;);
 // 定义一个枚举的集合 并进行循环来处理这个目录下的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) == &#39;/&#39;) {
    // 获取后面的字符串
    name = name.substring(1);
   }
   // 如果前半部分和定义的包名相同
   if (name.startsWith(packageDirName)) {
    int idx = name.lastIndexOf(&#39;/&#39;);
    // 如果以"/"结尾 是一个包
    if (idx != -1) {
    // 获取包名 把"/"替换成"."
    packageName = name.substring(0, idx).replace(&#39;/&#39;, &#39;.&#39;);
    }
    // 如果可以迭代下去 并且是一个包
    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 + &#39;.&#39; + className));
     } catch (ClassNotFoundException e) {
     e.printStackTrace();
     }
    }
    }
   }
   }
  } catch (IOException e) {
   e.printStackTrace();
  }
  }
 }
 } catch (IOException e) {
 e.printStackTrace();
 }

 return classes;
}

RequestMapping으로 주석이 달린 메소드를 찾고 주입된 매개변수를 찾아냅니다


//找也用了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;
}

이런 식으로 In 순수 서블릿으로 작성된 Java 프로젝트에서는 자신만의 주석 매핑 라우팅을 수행할 수 있으며 이는 매우 편리합니다

요약

위 내용은 Java가 리플렉션을 사용하여 지정된 주석을 사용하여 클래스를 찾는 방법에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.