自定义注解:通过监控文件的变化,实时更改工厂管理的实例
前言:之前一直想熟練自定義注解,但當時沒有實際的應用需求,也就是自己寫了個實例,就擱置下來了。 這回,是在做一個工程的時候,需要根據(jù)變化,注入新的實例到工廠。 為了方便,也是代碼整潔,就用到了自定義注解。
首先,有幾個點需要說明:
1,我需要監(jiān)控指定路徑的變化,比如:文件的刪除、文件的增加、修改等。 當文件刪除時,我需要銷毀工廠中的實例,并發(fā)出預警,做好備份。 當文件新增時(可能是class文件,也可能是jar包等)我需要逐層掃描注解,將新的實例注入到工廠備用 等等
2,目前做的實現(xiàn),只寫了class文件的遞歸掃描, 而且文件的監(jiān)控,還沒有寫具體的響應方法
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:最開始還以為這個玩意兒和之前寫的一個權(quán)限注解一樣的,原來當時用的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); } } } }解析注解,其實就很簡單,就跟實現(xiàn)一個接口一樣:確定當掃描到此注解時,需要執(zhí)行的工作。 比如說,此處:當我掃描到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() { //自定義過濾規(guī)則 @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)) 類似的判斷,隨后做相應的邏輯處理
四、總結(jié)
書到用時方恨少,但什么時候?qū)W習都不晚。 注解,是通過統(tǒng)一集中處理,從而給開發(fā)帶來方便,也使得代碼更為整潔。 但怎么說呢,凡事看需求吧,因為有時候注解是很方便,但在一些邏輯識別的時候,也有一定的阻礙。 ?
有時候我就在想,我們平時用到的一系列注解,到底都做了什么?它是怎么做到的?它的這種做法,是不是更好的?
在做這個注解的過程中,一個很大的體會: 既然要利用我提供的便利,那就得遵守我定下的規(guī)則!? 一切都是取舍平衡
附錄:文件監(jiān)控
1,定義文件變動時事件
import org.apache.commons.io.monitor.FileAlterationListenerAdaptor; import java.io.File; /** * 文件監(jiān)聽類—新增、修改、刪除excel模板 */ public class FileListener extends FileAlterationListenerAdaptor { @Override public void onFileCreate(File file) { System.out.println("[新建]:" + file.getAbsolutePath()); System.out.println("此時,調(diào)用注入方法,注入新添加的excel模板解析類"); } @Override public void onFileChange(File file) { System.out.println("[修改]:" + file.getAbsolutePath()); System.out.println("日志記錄,警告"); System.out.println("此時,銷毀舊的excel模板解析類,重新加載新的,但命名一定要能區(qū)分出更改的文件"); } @Override public void onFileDelete(File file) { System.out.println("[刪除]:" + file.getAbsolutePath()); System.out.println("此時,發(fā)布異常"); } }2,實施監(jiān)控
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; /** * 容器監(jiān)聽—根據(jù)文件監(jiān)聽的變化而變化 */ public class ContainerListener { public static void main(String[] args) throws Exception{ //?監(jiān)控目錄?? String rootDir = "example"; //?輪詢間隔?7 天—視情況而定? //long interval = TimeUnit.DAYS.toDays(7); long interval=TimeUnit.SECONDS.toMillis(10); FileAlterationObserver observer = new FileAlterationObserver( rootDir, //設(shè)置監(jiān)控過濾 FileFilterUtils.and( FileFilterUtils.fileFileFilter(), FileFilterUtils.suffixFileFilter(".java")), null); observer.addListener(new FileListener()); FileAlterationMonitor monitor = new FileAlterationMonitor(interval, observer); //?開始監(jiān)控?? monitor.start(); } }轉(zhuǎn)載于:https://www.cnblogs.com/hhx626/p/8320398.html
總結(jié)
以上是生活随笔為你收集整理的自定义注解:通过监控文件的变化,实时更改工厂管理的实例的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【十九】require和include的
- 下一篇: 《精通Spring4.X企业应用开发实战