• 自定义注解:通过监控文件的变化,实时更改工厂管理的实例


    前言:之前一直想熟练自定义注解,但当时没有实际的应用需求,也就是自己写了个实例,就搁置下来了。 这回,是在做一个工程的时候,需要根据变化,注入新的实例到工厂。 为了方便,也是代码整洁,就用到了自定义注解。 

    首先,有几个点需要说明:

    1,我需要监控指定路径的变化,比如:文件的删除、文件的增加、修改等。 当文件删除时,我需要销毁工厂中的实例,并发出预警,做好备份。 当文件新增时(可能是class文件,也可能是jar包等)我需要逐层扫描注解,将新的实例注入到工厂备用 等等

    2,目前做的实现,只写了class文件的递归扫描, 而且文件的监控,还没有写具体的响应方法

    3,基本步骤:首先:定义注解;其次:解析注解

    一、定义注解

    import java.lang.annotation.*;
    
    /**
     * 自定义excel模板注入注解
     */
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.TYPE,ElementType.METHOD})
    @Documented
    public @interface ExcelTemplate {
    
        //类名—必须录入
        String name();
    
        //提供当前模板解析的人
        String author() default "Angelina";
    
        //当前模板被提供的日期
        String supportedDate();
    
    }

    如果是必须录入的属性,就不要提供默认值,其余的一些属性,就自己查查吧     PS:最开始还以为这个玩意儿和之前写的一个权限注解一样的,原来当时用的Jeddict里面,提供了一些框架整合的东西,尴尬了。

    二、注解解析

        /**
         * 解析注解
         *
         * @param packageName 包名
         * @throws Exception
         */
        public void parsingAnnotation(String packageName) throws Exception {
            List<Class<?>> classes = getAllClass(packageName);
            if (!classes.isEmpty()) {
                AbstractExcelFactory excelFactory = AbstractExcelFactory.getInstance();
                for (Class _class : classes) {
                    if (_class.isAnnotationPresent(ExcelTemplate.class)) {
                        ExcelTemplate excelTemplate = (ExcelTemplate) _class.getAnnotation(ExcelTemplate.class);
                        //获取注解中的类名称
                        String name = excelTemplate.name();
                        String strBeanName=_class.getName();
                        // 注册
                        excelFactory.registryExcelReaderBean(name, strBeanName);
                    }
                }
            }
        }
    

    解析注解,其实就很简单,就跟实现一个接口一样:确定当扫描到此注解时,需要执行的工作。 比如说,此处:当我扫描到ExcelTemplate注解时,将其类实例注入到工厂。

    三、辅助查找所有包下的class文件方法

        /**
         * 获取包里所有的class文件
         *
         * @return
         * @throws IOException
         */
        public List<Class<?>> getAllClass(String packageName) throws IOException {
            Enumeration<URL> enumeration = Thread.currentThread().getContextClassLoader().getResources(packageName);
            List<Class<?>> classes = new ArrayList<Class<?>>();
            while (enumeration.hasMoreElements()) {
                URL url = enumeration.nextElement();
                String protocol = url.getProtocol();
                if ("file".equals(protocol)) {
                    String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
                    getAllFile(packageName, filePath, classes);
                }
            }
            return classes;
        }
    
    
        /**
         * 获取目录下的所有文件
         *
         * @param packageName 包名
         * @param packagePath 包的路径
         * @param classes     包下的所有类文件
         */
        public void getAllFile(String packageName, String packagePath, List<Class<?>> classes) {
            File fileDirector = new File(packagePath);
            File[] files = fileDirector.listFiles(new FileFilter() {
                //自定义过滤规则
                @Override
                public boolean accept(File file) {
                    return (true && file.isDirectory()) || (file.getName().endsWith(".class"));
                }
            });
            for (File file : files) {
                if (file.isDirectory()) {
                    String newPackageName = packageName + "." + file.getName();
                    String newPackagePath = file.getAbsolutePath();
                    getAllFile(newPackageName, newPackagePath, classes);
                } else {
                    String className = file.getName().substring(0, file.getName().length() - 6);
                    try {
                        classes.add(Class.forName(packageName + '.' + className));
                    } catch (ClassNotFoundException e) {
                        throw new ExcelException(ExceptionEnum.FAILDFINDTEMPLATE.getCode(),
                                ExceptionEnum.FAILDFINDTEMPLATE.getName());
                    }
                }
            }
        }

    这里只是处理了.class文件,如果要解析jar包,则需要做响应的判断和读取,如 if("file".equals(protocol)) 类似的判断,随后做相应的逻辑处理

    四、总结

    书到用时方恨少,但什么时候学习都不晚。 注解,是通过统一集中处理,从而给开发带来方便,也使得代码更为整洁。 但怎么说呢,凡事看需求吧,因为有时候注解是很方便,但在一些逻辑识别的时候,也有一定的阻碍。  

    有时候我就在想,我们平时用到的一系列注解,到底都做了什么?它是怎么做到的?它的这种做法,是不是更好的?

    在做这个注解的过程中,一个很大的体会: 既然要利用我提供的便利,那就得遵守我定下的规则!  一切都是取舍平衡


    附录:文件监控

    1,定义文件变动时事件

    import org.apache.commons.io.monitor.FileAlterationListenerAdaptor;
    
    import java.io.File;
    
    /**
     * 文件监听类—新增、修改、删除excel模板
     */
    public class FileListener extends FileAlterationListenerAdaptor {
        @Override
        public void onFileCreate(File file) {
            System.out.println("[新建]:" + file.getAbsolutePath());
            System.out.println("此时,调用注入方法,注入新添加的excel模板解析类");
        }
    
        @Override
        public void onFileChange(File file) {
            System.out.println("[修改]:" + file.getAbsolutePath());
            System.out.println("日志记录,警告");
            System.out.println("此时,销毁旧的excel模板解析类,重新加载新的,但命名一定要能区分出更改的文件");
        }
    
        @Override
        public void onFileDelete(File file) {
            System.out.println("[删除]:" + file.getAbsolutePath());
            System.out.println("此时,发布异常");
        }
    }
    

    2,实施监控

    import org.apache.commons.io.filefilter.FileFilterUtils;
    import org.apache.commons.io.monitor.FileAlterationMonitor;
    import org.apache.commons.io.monitor.FileAlterationObserver;
    
    import java.util.concurrent.TimeUnit;
    
    /**
     * 容器监听—根据文件监听的变化而变化
     */
    public class ContainerListener {
        public static void main(String[] args) throws Exception{
            // 监控目录  
            String rootDir = "example";
            // 轮询间隔 7 天—视情况而定 
            //long interval = TimeUnit.DAYS.toDays(7);
            long interval=TimeUnit.SECONDS.toMillis(10);
            FileAlterationObserver observer = new FileAlterationObserver(
                    rootDir,
                    //设置监控过滤
                    FileFilterUtils.and(
                            FileFilterUtils.fileFileFilter(),
                            FileFilterUtils.suffixFileFilter(".java")),
                    null);
            observer.addListener(new FileListener());
            FileAlterationMonitor monitor = new FileAlterationMonitor(interval, observer);
            // 开始监控  
            monitor.start();
        }
    }
    




  • 相关阅读:
    mysql 8 查询报错(sql_mode=only_full_group_by)
    docker安装mysql8版本后 客户端连接出现client does not support authentication...
    docker常用命令
    查看tomcat日志相关Linux命令
    java项目部署到linux服务器涉及的命令
    ehcache与redis对比
    JS中调用BigDecimal处理金额
    thymeleaf模板 th:href 踩坑
    汇总一些绝对有价值的解决方案,边学习边收集
    spring注解总结,spring注解大全
  • 原文地址:https://www.cnblogs.com/hhx626/p/8320398.html
Copyright © 2020-2023  润新知