精华内容
下载资源
问答
  • 前几天项目中让扫描出...主要包含如下三个步骤:java根据包名解析包的具体路径查找指定包下指定注解的类在上一步骤中获得的类中,依次扫描包含指定注解的方法想着写着工具类的形式,代码结构以下:pythonpublic class ...

    前几天项目中让扫描出全部使用Restful API的方法。刚开始还想着用python过滤关键字来查找的,后来想一想能够使用反射来搞的。主要包含如下三个步骤:java

    根据包名解析包的具体路径

    查找指定包下指定注解的类

    在上一步骤中获得的类中,依次扫描包含指定注解的方法

    想着写着工具类的形式,代码结构以下:python

    public class AnnotationScannerUtils {

    private static final Logger logger = LoggerFactory.getLogger(AnnotationScannerUtils.class);

    private static final String EXT = "class

    /**

    * 根据包名获取包的URL

    * @param pkgName com.demo.controller

    * @return

    */

    public static String getPkgPath(String pkgName){

    String pkgDirName = pkgName.replace('.', File.separatorChar);

    URL url = Thread.currentThread().getContextClassLoader().getResource(pkgDirName);

    return url == null ? null : url.getFile();

    }

    /**

    * 获取指定包下全部类对象的集合

    * @param pkgName 包名(com.demo.controller)

    * @param pkgPath 包路径(/Users/xxx/workspace/java/project/out/production/classes/com/demo/controller)

    * @param recursive 是否递归遍历子目录

    * @return 类集合

    */

    public static Set> scanClasses(String pkgName, String pkgPath, final boolean recursive){

    Set> classesSet = new HashSet<>();

    Collection allClassFile = getAllClassFile(pkgPath, recursive);

    for (File curFile : allClassFile){

    try {

    classesSet.add(getClassObj(curFile, pkgPath, pkgName));

    } catch (ClassNotFoundException e) {

    logger.error("load class fail", e);

    }

    }

    return classesSet;

    }

    /**

    * 获取指定包下包含指定注解的全部类对象的集合

    * @param pkgName 包名(com.demo.controller)

    * @param pkgPath 包路径(/Users/xxx/workspace/java/project/out/production/classes/com/demo/controller)

    * @param recursive 是否递归遍历子目录

    * @param targetAnnotations 指定注解

    * @return 以注解和对应类集合构成的键值对

    */

    public static Map, Set>> scanClassesByAnnotations(

    String pkgName, String pkgPath, final boolean recursive, List> targetAnnotations){

    Map, Set>> resultMap = new HashMap<>(16);

    Collection allClassFile = getAllClassFile(pkgPath, recursive);

    for (File curFile : allClassFile){

    try {

    Class> curClass = getClassObj(curFile, pkgPath, pkgName);

    for (Class extends Annotation> annotation : targetAnnotations){

    if (curClass.isAnnotationPresent(annotation)){

    if (!resultMap.containsKey(annotation)){

    resultMap.put(annotation, new HashSet>());

    }

    resultMap.get(annotation).add(curClass);

    }

    }

    } catch (ClassNotFoundException e) {

    logger.error("load class fail", e);

    }

    }

    return resultMap;

    }

    /**

    * 加载类

    * @param file

    * @param pkgPath

    * @param pkgName

    * @return

    * @throws ClassNotFoundException

    */

    private static Class> getClassObj(File file, String pkgPath, String pkgName) throws ClassNotFoundException{

    // 考虑class文件在子目录中的状况

    String absPath = file.getAbsolutePath().substring(0, file.getAbsolutePath().length() - EXT.length() - 1);

    String className = absPath.substring(pkgPath.length()).replace(File.separatorChar, '.');

    className = className.startsWith(".") ? pkgName + className : pkgName + "." + className;

    return Thread.currentThread().getContextClassLoader().loadClass(className);

    }

    /**

    * 遍历指定目录下全部扩展名为class的文件

    * @param pkgPath 包目录

    * @param recursive 是否递归遍历子目录

    * @return

    */

    private static Collection getAllClassFile(String pkgPath, boolean recursive){

    File fPkgDir = new File(pkgPath);

    if (!(fPkgDir.exists() && fPkgDir.isDirectory())){

    logger.error("the directory to package is empty: {}", pkgPath);

    return null;

    }

    return FileUtils.listFiles(fPkgDir, new String[]{EXT}, recursive);

    }

    /**

    * 查找指定注解的Method

    * @param classes 查找范围

    * @param targetAnnotations 指定的注解

    * @return 以注解和对应Method类集合构成的键值对

    */

    public static Map, Set> scanMethodsByAnnotations(Set> classes,

    List> targetAnnotations){

    Map, Set> resultMap = new HashMap<>(16);

    for (Class> cls : classes){

    Method[] methods = cls.getMethods();

    for (Class extends Annotation> annotation : targetAnnotations){

    for (Method method : methods){

    if (method.isAnnotationPresent(annotation)){

    if (!resultMap.containsKey(annotation)){

    resultMap.put(annotation, new HashSet());

    }

    resultMap.get(annotation).add(method);

    }

    }

    }

    }

    return resultMap;

    }

    }

    复制代码

    具体使用时,可根据具体状况在原方法上二次开发。若是是直接调用,能够实现扫描包含指定注解的类和方法:web

    public static void main(String[] args){

    String pkgName = "com.demo.controller";

    String pkgPath = getPkgPath(pkgName);

    logger.info("pkgPath is {}", pkgName);

    // 查找包含RestController和Controller注解的类

    Map, Set>> classesMap = scanClassesByAnnotations(pkgName, pkgPath, true,

    Arrays.asList(RestController.class, Controller.class));

    if (classesMap.size() == 0){

    logger.error("Not exists any class in {} with the specified annotation", pkgPath);

    return;

    }

    Set> classSet = new HashSet<>();

    classesMap.forEach((k, v) -> {

    logger.info("get {} classes with {}", v.size(), k.getSimpleName());

    classSet.addAll(v);

    });

    // 查找包含GetMapping和PostMapping注解的Method

    Map, Set> methodMap = scanMethodsByAnnotations(classSet, Arrays.asList(GetMapping.class, PostMapping.class));

    if (methodMap.size() == 0){

    logger.error("Not exists any method with the specified annotation");

    return;

    }

    methodMap.forEach((k, v) -> {

    StringBuilder sb = new StringBuilder();

    v.forEach(method -> sb.append(method.getName()+", "));

    logger.info(k.getSimpleName() + ": " + sb.toString());

    });

    }

    --------------------------output-------------------------

    01-20 15:06:02.293 [ INFO] [ m.i.u.AnnotationScannerUtils: 29] - pkgPath is com.demo.controller

    01-20 15:06:02.363 [ INFO] [ m.i.u.AnnotationScannerUtils: 41] - get 5 classes with RestController

    01-20 15:06:02.374 [ INFO] [ m.i.u.AnnotationScannerUtils: 41] - get 2 classes with Controller

    01-20 15:06:02.388 [ INFO] [ m.i.u.AnnotationScannerUtils: 55] - PostMapping: login, addFavorite, addUser, logout,

    01-20 15:06:02.388 [ INFO] [ m.i.u.AnnotationScannerUtils: 55] - GetMapping: webSiteInfo, info, getCategories, favoritesList, getReportByCityId, queryUserById, getReportByCityName, queryBookById,

    复制代码

    展开全文
  • 我们常常有扫描项目里带有指定注解的class, 下面是利用spring扫描自定义注解的方法, 还是比较灵活的我这里将扫描到的class放到map, 你可以放到其他地方,以便后期使用import lombok.extern.slf4j.Slf4j;import org....

    我们常常有扫描项目里带有指定注解的class, 下面是利用spring扫描自定义注解的方法, 还是比较灵活的

    我这里将扫描到的class放到map, 你可以放到其他地方,以便后期使用

    import lombok.extern.slf4j.Slf4j;

    import org.apache.shiro.SecurityUtils;

    import org.apache.shiro.session.Session;

    import org.springframework.context.ApplicationEvent;

    import org.springframework.context.ApplicationListener;

    import org.springframework.core.io.Resource;

    import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

    import org.springframework.core.io.support.ResourcePatternResolver;

    import org.springframework.core.type.classreading.CachingMetadataReaderFactory;

    import org.springframework.core.type.classreading.MetadataReader;

    import org.springframework.core.type.classreading.MetadataReaderFactory;

    import org.springframework.util.ClassUtils;

    import org.springframework.util.StringUtils;

    import javax.persistence.Table;

    import java.io.IOException;

    import java.util.HashMap;

    import java.util.Map;

    import java.util.concurrent.ConcurrentHashMap;

    /**

    * 扫描指定包下带有指定注解的class

    * @author jaffreyen

    * @date 2018/3/5

    */

    @Slf4j

    public class MyApplicationListener implements ApplicationListener {

    /**

    * Handle an application event.

    *

    * @param event the event to respond to

    */

    @Override

    public void onApplicationEvent(ApplicationEvent event) {

    ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();

    final String RESOURCE_PATTERN = "/**/*.class";

    // 扫描的包名

    final String BASE_PACKAGE = "com.xxx";

    Map> classCache = new HashMap<>();

    try {

    String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + ClassUtils.convertClassNameToResourcePath(BASE_PACKAGE)

    + RESOURCE_PATTERN;

    Resource[] resources = resourcePatternResolver.getResources(pattern);

    MetadataReaderFactory readerFactory = new CachingMetadataReaderFactory(resourcePatternResolver);

    for (Resource resource : resources) {

    if (resource.isReadable()) {

    MetadataReader reader = readerFactory.getMetadataReader(resource);

    //扫描到的class

    String className = reader.getClassMetadata().getClassName();

    Class> clazz = Class.forName(className);

    //判断是否有指定注解

    Table annotation = clazz.getAnnotation(Table.class);

    if(annotation != null){

    //这个类使用了自定义注解

    classCache.put(className, clazz);

    }

    }

    }

    } catch (IOException | ClassNotFoundException e) {

    log.error("读取class失败", e);

    }

    }

    }

    展开全文
  • importjava.io.File;importjava.lang.reflect.InvocationTargetException;importjava.lang.reflect.Method;importjava.net.URL;importjava.util.ArrayList;importjava.util.Enumeration;importjava.util.HashMap;imp...

    importjava.io.File;importjava.lang.reflect.InvocationTargetException;importjava.lang.reflect.Method;importjava.net.URL;importjava.util.ArrayList;importjava.util.Enumeration;importjava.util.HashMap;importjava.util.List;importjava.util.Map;/*** 扫描类

    *

    *@authorAdministrator

    **/

    public classJavaScan {/*** 存放 文件根路径*/

    staticString classPath;/*** 存放结果*/

    static List classPathList = new ArrayList<>();/*** 使用类全名定义的bean容器*/

    static Map> beans = new HashMap<>();/*** 使用方法的注解的url属性定义的classes容器*/

    static Map> classes = new HashMap<>();/*** method 容器*/

    static Map methods = new HashMap<>();/*** 初始化

    *

    *@return*@throwsException*/

    public static void init(String path) throwsException {if (null ==path)throw new NullPointerException("JavaScan.init(String path) 参数不能为null");//初始化 获取项目的 classPath 路径,File.separator:\

    classPath = new File(getRootPath()).getPath() +File.separator;//总结:String classPathNoseparator = new File(rootPath).getPath()//结果:G:\woorkspace\servletdemo\javaweb-servlet-demo\build\classes//使用 IO扫描 指定路径下的所有文件

    getFileName(classPath +path);//使用 所有类命名字符串来 初始化容器

    initContainer();

    }/*** 获取rootPath的相关的根路径

    * getResources("") 如果放为空串儿,那么就是获取rootPath的相关的根路径

    *

    *@returnrootPath的相关的根路径

    *@throwsException*/

    private static String getRootPath() throwsException {//注: main方法启动 获取路径方式//Enumeration resources = JavaScan.class.getClassLoader().getResources("");//注: servlet启动 获取路径方式

    Enumeration resources = JavaScan.class.getClassLoader().getResources("/");

    URL url=resources.nextElement();returnurl.getPath();//总结:String rootPath = this.getClass().getClassLoader().getResources("").nextElement().getPath()//结果:/G:/woorkspace/servletdemo/javaweb-servlet-demo/build/classes/

    }/*** 使用 IO扫描 Class文件*/

    private static voidgetFileName(String rootPath) {

    File file= newFile(rootPath);//获取所有文件和文件夹

    File[] fileList =file.listFiles();for (int i = 0; null != fileList && i < fileList.length; i++) {

    String path=fileList[i].getPath();//如果是目录

    if(fileList[i].isDirectory()) {//继续递归

    getFileName(path);

    }if(fileList[i].isFile()) {//输出 所有文件夹下的全路径//System.out.println(path);//拼接类路径保存到集合中,(类路径所指的是 去掉根路径以外的项目中 class的全路径)//path.replace(fileRootPath, "") 去除根路径//.replaceAll(".class", "") 去掉后缀名//.replaceAll(File.separator + File.separator, ".") 将斜杠'\或/'转成//点'.'

    String classpath = path.replace(classPath, "").replaceAll(".class", "")

    .replaceAll(File.separator+ File.separator, ".");

    classPathList.add(classpath);

    }

    }

    }/*** 使用 所有类全命名来 初始化容器

    *

    *@throwsException*/

    private static void initContainer() throwsException {if (null == classPathList || classPathList.size() <= 0)throw new Exception("文件路径不存在!" + JavaScan.class.getName());//获取 所有类的类全名

    for (int i = 0; i < classPathList.size(); i++) {

    String className=classPathList.get(i);

    Class> forName =Class.forName(className);//初始化限制,初始化的文件类型必须是 class文件

    if (!forName.isAnnotation() && !forName.isEnum() && !forName.isInterface()) {//只初始化 实现了CustomAnnotationBean注解的类

    if (forName.isAnnotationPresent(CustomAnnotationBean.class)) {//初始化类对象 添加到容器中

    if (!beans.containsKey(className))

    beans.put(className, forName);

    }//只初始化 实现了CustomAnnotationBean注解的类中的方法

    Method[] methodArray =forName.getDeclaredMethods();for(Method method : methodArray) {//初始化 实现了CustomAnnotationMethod注解的方法

    if (method.isAnnotationPresent(CustomAnnotationMethod.class)) {//获取注解

    CustomAnnotationMethod annotation = method.getAnnotation(CustomAnnotationMethod.class);//获取注解的属性

    String attr =annotation.uri();if (!methods.containsKey(attr)) {//初始化方法 添加到容器中

    methods.put(attr, method);//将此方法对应的类 添加到容器中

    classes.put(attr, forName);

    }

    }

    }

    }

    }

    }/*** 执行 method

    *

    *@paramurl

    *@return*@throwsInvocationTargetException

    *@throwsIllegalAccessException

    *@throwsInstantiationException

    *@throwsIllegalArgumentException*/

    publicObject executeMethod(String url, Object... args)throwsInvocationTargetException, IllegalAccessException, IllegalArgumentException, InstantiationException {if (null == url || "".equals(url))throw new NullPointerException("ApiPool.executeMethod(String url):参数不能为null");returnmethods.get(url).invoke(classes.get(url).newInstance(), args);

    }/*** 获取 使用类全名定义的bean容器

    *

    *@return

    */

    public Map>getBeans() {returnbeans;

    }/*** 获取 使用类全名定义的bean

    *

    *@return

    */

    public Class>getBean(String key) {returnbeans.get(key);

    }/*** 获取 使用方法的注解的url属性定义的classes容器

    *

    *@return

    */

    public Map>getClazzs() {returnclasses;

    }/*** 获取 使用方法的注解的url属性定义的classes

    *

    *@return

    */

    public Class>getClazz(String key) {returnclasses.get(key);

    }/*** 获取Method容器

    *

    *@return

    */

    public MapgetMethods() {returnmethods;

    }/*** 获取Method

    *

    *@return

    */

    publicMethod getMethod(String key) {returnmethods.get(key);

    }/*** 测试

    *

    *@paramargs

    *@throwsException*/

    public static void main(String[] args) throwsException {

    JavaScan javaScan= newJavaScan();//在main 方法中调用传空串就可以

    javaScan.init("");for(String key : javaScan.getBeans().keySet()) {

    Object object=javaScan.getBean(key);

    System.out.println(object);

    }

    }

    }

    展开全文
  • 我有几个需要用名称注释的类,因此我将注释定义为@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)public @interface JsonUnmarshallable {public String value();}现在,需要此注释的类定义为@...

    我有几个需要用名称注释的类,因此我将注释定义为

    @Retention(RetentionPolicy.RUNTIME)

    @Target(ElementType.TYPE)

    public @interface JsonUnmarshallable {

    public String value();

    }

    现在,需要此注释的类定义为

    @JsonUnmarshallable("myClass")

    public class MyClassInfo {

    }

    我使用下面的代码来扫描注释

    private Map scanForAnnotation(Class annotationType) {

    GenericApplicationContext applicationContext = new GenericApplicationContext();

    ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(applicationContext, false);

    scanner.addIncludeFilter(new AnnotationTypeFilter(annotationType));

    scanner.scan("my");

    applicationContext.refresh();

    return (Map) applicationContext.getBeansWithAnnotation(annotationType);

    }

    问题是返回的映射包含,["myClassInfo" -> object of

    MyClassInfo]但是我需要映射包含"myClass"作为键,这是Annotation的值而不是bean名称。

    有办法吗?

    展开全文
  • 方案一:采用reflections 框架(此框架依赖com.google.guava)2、项目依赖org.reflectionsreflections0.9.11 com.google.guava guava21.03、实现代码//入参 要扫描的包名Reflections f = new Reflections(...
  • } /** * 获取指定路径下的类 * * @param pkgPath * @param annoClazz * @return */ public static Set getClazzFromAnnotation(String pkgPath, Class extends Annotation> annoClazz) { //获取spring的包路径 ...
  • 只有当组件定义前面有下面的注解标记时,这些组件才会被扫描到Spring容器- @Component 通用注解- @Name 通用注解- @Repository 持久化层组件注解- @Service 业务层组件注解- @Controller 控制层组件注解命名组件...
  • 前几天项目中让扫描出所有使用Restful ...查找指定包下指定注解的类 在上一步骤中得到的类中,依次扫描包含指定注解的方法 想着写着工具类的形式,代码结构如下: public class AnnotationScannerUtils { private...
  • java通过反射的类扫描工具类,通过反射找到类的字节码, package com.csnt.scdp.bizmodules.modules.util; import java.io.File; import java.io.IOException; import java.net.JarURLConnection; import ...
  • @Autowired和@Resource区别:在Java中使用@Autowired和@Resource注解进行装配,这两个注解分别是:1、@Autowired按照默认类型(名称)装配依赖对象,默认情况下它要求依赖对象必须存在,如果允许为null,可以设置它...
  • 1、定义一个用来标识的类注解 package test.qifanedu.reflection; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import ...
  • public classScanner {/*** 从包package中获取所有Class**@parampackageName*@... getClasses(String packageName) throwsException{//第一个class类的集合//List> classes = new ArrayList>();Set>...
  • 作者:俊俊小熊饼干cnblogs.com/wenjunwei/p/10293490.html前言最近在做项目权限,使用shiro实现restful接口权限管理,对整个项目都进行了重构。而权限管理需要用到所有接口配置,包括接口url...使用Auth.java...
  • 方案一: 采用reflections 框架(此框架依赖com.google.guava)2、项目依赖org.reflectionsreflections0.9.11 com.google.guava guava21.03、实现代码//入参 要扫描的包名Reflections f = new Reflections(...
  • 最近在学习java的反射和注解,实际情景中需要扫描某个包下所有java类,然后使用加载器加载。基本思路,获得程序路径扫描src下某个包内子包和java类,实现也比较简单。运行环境:windows10+jdk1.8+eclipse...
  • import java.util.HashMap; import java.util.Map; import java.util.TreeMap; import org.tio.http.server.annotation.RequestPath; import org.tio.http.server.demo1.HttpServerDemoStarter; import io.gith...
  • 目的:通过加载器加载 PeopleImpl ,获取该中含有@AutoWrite 注解的字段,并获取到这个字段的类型然后初始化它。 首先,我们需要自定义一个最简单的注解( 没有参数 ),注解名为:AutoWrite  import java....
  • 方案一:采用reflections 框架(此框架依赖com.google.guava)2、项目依赖org.reflectionsreflections0.9.11 com.google.guava guava21.03、实现代码//入参 要扫描的包名Reflections f = new Reflections(...
  • 1、接口回调package ...import java.io.File;public interface IWhat { void execute(File file,Class<?> clazz); }2、扫描方法public static void scanPackage(String iPackage,IWhat what){
  •  不需要指定需要类加载器进行加载的类,改为通过扫描所有的类并通过类加载器进行加载;  2. 获取所有类中含@AutoWrite 注解的字段,获取到字段的类型并初始化。 首先,我们需要自定义一个最简单的注解类( ...
  • 方案一: 采用reflections 框架(此框架依赖com.google.guava)1、reflections框架地址:https://github.com/ronmamo/reflections2、项目依赖org.reflectionsreflections0.9.11 ...要扫描的包名Reflections f = ne...
  • 内容(这篇只是一些新手入门,进阶请看番外)1 什么是组件扫描2 指定扫描路径3 自动扫描注解标记4 自动扫描注解命名5 指定组件作用域6 指定初始化和销毁方法7 指定依赖注入关系8 注入spring表达式1 什么是组件...
  • 比如在上使用该注解 @Alias("dDebtEntity")则在mapper.xml文件中resultType="dDebtEntity"在myBatisConfig.xml中sqlSessionFactory需要配置注解 需要扫路径Mybatis之typeAlias配置3种方法1.定义别名:2.扫描包...
  • 最近在学习java的反射和注解,实际情景中需要扫描某个包下所有java类,然后使用加载器加载。基本思路,获得程序路径扫描src下某个包内子包和java类,实现也比较简单。运行环境:windows10+jdk1.8+eclipse...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,440
精华内容 576
关键字:

java扫描注解的类

java 订阅