zoukankan      html  css  js  c++  java
  • Java扫描包

    在Java中,经常会有 “ 扫描某个包,然后找出全部的Class ” 的需求。

    Spring对这方面提供了支持,直接用即可,AbstractApplicationContext (上下文)、ConfigurableListableBeanFactory(BeanFactory)等对象
    都可以实现扫描包的效果。

    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
    import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
    import org.springframework.stereotype.Controller;
    
    class BeanFactoryPostProcessorExample implements BeanFactoryPostProcessor {
    
        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
            //获取带有Controller注解的Bean
            String[] names= beanFactory.getBeanNamesForAnnotation(Controller.class);
        }
    }

    Reflections这个工具包也很不错,Maven的依赖如下:

        <dependency>
          <groupId>com.google.guava</groupId>
          <artifactId>guava</artifactId>
          <version>22.0</version>
        </dependency>
        <dependency>
          <groupId>org.reflections</groupId>
          <artifactId>reflections</artifactId>
          <version>0.9.10</version>
        </dependency>
        <dependency>
          <groupId>org.javassist</groupId>
          <artifactId>javassist</artifactId>
          <version>3.15.0-GA</version>
        </dependency>
            Reflections reflections = new Reflections("com.sea.server.hessian");
            Set<Class<?>> hessianImpls = reflections.getTypesAnnotatedWith(Controller.class);

    Java扫描包

    因为是偏底层的东西,自己编码虽然可以实现,但是代码安全会是一个非常麻烦的问题;

    代码直接通过IO流转对象的方式实现,代码运行成功的前提是.class文件必须没有问题,.class文件出问题,代码就无法正常运行;

    (当作是学习和交流吧,改进方案是对.class文件进行校验,校验通过之后,再将.class文件转换为Class对象,如果有兴趣自己继续完善吧,我已经弃坑了)。

    import java.io.ByteArrayOutputStream;
    import java.io.File;
    import java.io.FileFilter;
    import java.io.FileInputStream;
    import java.nio.ByteBuffer;
    import java.nio.channels.Channels;
    import java.nio.channels.FileChannel;
    import java.nio.channels.WritableByteChannel;
    import java.util.ArrayList;
    import java.util.List;
    
    import com.sea.common.util.Resource;
    import com.sea.common.util.StrStream;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    /**
     * 编译任意class文件,需要保证class文件可用,否则ERROR
     * 
     * @author ChenSS 2017年8月25日上午10:04:38
     *
     */
    @Deprecated
    public class MyClassLoader extends ClassLoader{
        private static Logger logger = LoggerFactory.getLogger(ClassLoader.class);
    
        public MyClassLoader() {
            super(Resource.getClassLoader());
        }
        
        public static void main(String[] args) throws ClassNotFoundException {
            MyClassLoader loader = new MyClassLoader();
            try {
                List<Class<?>> clazz = loader.load("C:/Users/ChenSS/Desktop/代码测试/build/classes/", "com.css.common.util");
                System.out.println(clazz);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        public List<Class<?>> load(String location, String pkg) {
            return load(new File(location), pkg);
        }
    
        public List<Class<?>> load(File file, String pkg) {
            //StrStream是自定义的字符串校验工具,用于查找前缀是pkg(包名)、并且不包含美元符的文件
            StrStream stream = new StrStream().prefix(pkg).notExists('$');
            return load(file, stream);
        }
    
        public List<Class<?>> load(File file, StrStream stream) {
            List<Class<?>> classes = new ArrayList<>();
            if (file.exists() && file.isDirectory()) {
                for (File dir : likeFile(file, "", stream)) {
                    if (dir.isDirectory()) {
                        traverseFile(dir, dir.getName(), classes, stream);
                    } else {
                        // 根目录的class
                    }
                }
            }
            return classes;
        }
    
        /**
         * 递归搜索全部文件,查找全部.class文件
         * @param dir
         * @param pkg
         * @param classes
         * @param stream
         */ 
        public void traverseFile(File dir, String pkg, List<Class<?>> classes, StrStream stream) {
            for (File file : likeFile(dir, pkg, stream)) {
                if (file.isDirectory()) {
                    //文件夹就遍历下一级目录
                    traverseFile(file, pkg + '.' + file.getName(), classes, stream);
                } else {
                    //根据.class文件直接生成Class<?>
                    String className = null;
                    try {
                        String fileName = file.getName();
                        className = pkg + '.' + fileName.substring(0, fileName.length() - 6);
                        Class<?> clazz = format(file, className);
                        logger.debug(clazz.toString());
                        classes.add(clazz);
                    } catch (Exception e) {
                        e.printStackTrace();
                        logger.error(className + " : load error");
                        continue;
                    }
                }
            }
        }
    
        public Class<?> format(String fileName, String className) throws Exception {
            return format(new File(fileName), className);
        }
    
        /**
         * 从.class文件直接生成Class<?>,从IO到对象的转换,IO是未经过检查的;
         * 因此,如果想要使用此类,必须保证全部的.class文件可以创建Java类;
         * 手动编码、并且编译通过的.class文件不会有问题;
         * 扫描自己不熟悉的.class文件时,如果.class文件内容是错误的,有可能产生强制中断主函数的Error。
         */
        public Class<?> format(File file, String className) throws Exception {
            FileInputStream fis = new FileInputStream(file);
            FileChannel fileC = fis.getChannel();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            WritableByteChannel wbc = Channels.newChannel(baos);
            ByteBuffer buffer = ByteBuffer.allocateDirect(1024);
            while (fileC.read(buffer) > 0) {
                buffer.flip();
                wbc.write(buffer);
                buffer.clear();
            }
            byte[] b = baos.toByteArray();
            IOUtils.closeQuietly(baos, wbc, fileC, fis);
            return defineClass(className, b, 0, b.length);
        }
    
        /**
         * 
         * @param dir 文件夹
         * @param string 路径名
         * @param stream 字符串校验类
         * @return
         */
        public static File[] likeFile(File dir, String string, StrStream stream) {
            return dir.listFiles(new FileFilter() {
    
                @Override
                public boolean accept(File file) {
                    return stream.string(string).like() || file.isFile();
                }
            });
        }
    }
  • 相关阅读:
    python convert csv to xlsx
    org.openqa.selenium.remote.SessionNotFoundException: The FirefoxDriver cannot be used after quit() was called.
    Selenium webdriver 操作日历控件
    SVN eclipse插件错误
    java.lang.UnsupportedClassVersionError: Unsupported major.minor version 52.0的错误
    如何获取web中某个元素的id
    Selenium 进行web自动化测试
    Navicat远程连接MySQL数据库
    Linux grep命令详解
    Linux awk命令详解
  • 原文地址:https://www.cnblogs.com/chenss15060100790/p/9158011.html
Copyright © 2011-2022 走看看