<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          SpringBoot 定時(shí)任務(wù)動(dòng)態(tài)管理通用解決方案

          共 17836字,需瀏覽 36分鐘

           ·

          2022-01-01 18:20

          點(diǎn)擊關(guān)注公眾號(hào),Java干貨及時(shí)送達(dá)??


          一、功能說(shuō)明

          SpringBoot的定時(shí)任務(wù)的加強(qiáng)工具,實(shí)現(xiàn)對(duì)SpringBoot原生的定時(shí)任務(wù)進(jìn)行動(dòng)態(tài)管理,完全兼容原生@Scheduled注解,無(wú)需對(duì)原本的定時(shí)任務(wù)進(jìn)行修改

          二、快速使用

          具體的功能已經(jīng)封裝成SpringBoot-starter即插即用

          <dependency>
          ????<groupId>com.github.guoyixinggroupId>
          ????<artifactId>spring-boot-starter-super-scheduledartifactId>
          ????<version>0.3.1version>
          dependency>

          使用方法和源碼:

          碼云:https://gitee.com/qiaodaimadewangcai/super-scheduled

          github:https://github.com/guoyixing/super-scheduled

          三、實(shí)現(xiàn)原理

          1、動(dòng)態(tài)管理實(shí)現(xiàn)

          (1) 配置管理介紹

          @Component("superScheduledConfig")
          public?class?SuperScheduledConfig?{
          ????/**
          ?????*?執(zhí)行定時(shí)任務(wù)的線程池
          ?????*/

          ????private?ThreadPoolTaskScheduler?taskScheduler;

          ????/**
          ?????*?定時(shí)任務(wù)名稱與定時(shí)任務(wù)回調(diào)鉤子??的關(guān)聯(lián)關(guān)系容器
          ?????*/

          ????private?Map?nameToScheduledFuture?=?new?ConcurrentHashMap<>();

          ????/**
          ?????*?定時(shí)任務(wù)名稱與定時(shí)任務(wù)需要執(zhí)行的邏輯??的關(guān)聯(lián)關(guān)系容器
          ?????*/

          ????private?Map?nameToRunnable?=?new?ConcurrentHashMap<>();

          ????/**
          ?????*?定時(shí)任務(wù)名稱與定時(shí)任務(wù)的源信息??的關(guān)聯(lián)關(guān)系容器
          ?????*/

          ????private?Map?nameToScheduledSource?=?new?ConcurrentHashMap<>();
          ?/*?普通的get/sets省略?*/
          }

          (2) 使用后處理器攔截SpringBoot原本的定時(shí)任務(wù)

          • 實(shí)現(xiàn)ApplicationContextAware接口拿到SpringBoot的上下文
          • 實(shí)現(xiàn)BeanPostProcessor接口,將這個(gè)類標(biāo)記為后處理器,后處理器會(huì)在每個(gè)bean實(shí)例化之后執(zhí)行
          • 使用@DependsOn注解強(qiáng)制依賴SuperScheduledConfig類,讓SpringBoot實(shí)例化SuperScheduledPostProcessor類之前先實(shí)例化SuperScheduledConfig類
          • 主要實(shí)現(xiàn)邏輯在postProcessAfterInitialization()方法中
          @DependsOn({"superScheduledConfig"})
          @Component
          @Order
          public?class?SuperScheduledPostProcessor?implements?BeanPostProcessor,?ApplicationContextAware?{
          ????protected?final?Log?logger?=?LogFactory.getLog(getClass());

          ????private?ApplicationContext?applicationContext;

          ????/**
          ?????*?實(shí)例化bean之前的操作
          ?????*?@param?bean?bean實(shí)例
          ?????*?@param?beanName?bean的Name
          ?????*/

          ????@Override
          ????public?Object?postProcessBeforeInitialization(Object?bean,?String?beanName)?throws?BeansException?{
          ????????return?bean;
          ????}

          ????/**
          ?????*?實(shí)例化bean之后的操作
          ?????*?@param?bean?bean實(shí)例
          ?????*?@param?beanName?bean的Name
          ?????*/

          ????@Override
          ????public?Object?postProcessAfterInitialization(Object?bean,
          ?????????????????????????????????????????????????String?beanName)
          ?throws?BeansException?
          {
          ????????//1.獲取配置管理器
          ????????SuperScheduledConfig?superScheduledConfig?=?applicationContext.getBean(SuperScheduledConfig.class);

          ????????//2.獲取當(dāng)前實(shí)例化完成的bean的所有方法
          ????????Method[]?methods?=?bean.getClass().getDeclaredMethods();
          ????????//循環(huán)處理對(duì)每個(gè)方法逐一處理
          ????????if?(methods.length?>?0)?{
          ????????????for?(Method?method?:?methods)?{
          ?????????????//3.嘗試在該方法上獲取@Scheduled注解(SpringBoot的定時(shí)任務(wù)注解)
          ????????????????Scheduled?annotation?=?method.getAnnotation(Scheduled.class);
          ????????????????//如果無(wú)法獲取到@Scheduled注解,就跳過(guò)這個(gè)方法
          ????????????????if?(annotation?==?null)?{
          ????????????????????continue;
          ????????????????}
          ????????????????//4.創(chuàng)建定時(shí)任務(wù)的源屬性
          ????????????????//創(chuàng)建定時(shí)任務(wù)的源屬性(用來(lái)記錄定時(shí)任務(wù)的配置,初始化的時(shí)候記錄的是注解上原本的屬性)
          ????????????????ScheduledSource?scheduledSource?=?new?ScheduledSource(annotation,?method,?bean);
          ????????????????//對(duì)注解上獲取到源屬性中的屬性進(jìn)行檢測(cè)
          ????????????????if?(!scheduledSource.check())?{
          ????????????????????throw?new?SuperScheduledException("在"?+?beanName?+?"Bean中"?+?method.getName()?+?"方法的注解參數(shù)錯(cuò)誤");
          ????????????????}
          ????????????????//生成定時(shí)任務(wù)的名稱(id),使用beanName+“.”+方法名
          ????????????????String?name?=?beanName?+?"."?+?method.getName();
          ????????????????//將以key-value的形式,將源數(shù)據(jù)存入配置管理器中,key:定時(shí)任務(wù)的名稱 value:源數(shù)據(jù)
          ????????????????superScheduledConfig.addScheduledSource(name,?scheduledSource);
          ????????????????try?{
          ?????????????????//5.將原本SpringBoot的定時(shí)任務(wù)取消掉
          ????????????????????clearOriginalScheduled(annotation);
          ????????????????}?catch?(Exception?e)?{
          ????????????????????throw?new?SuperScheduledException("在關(guān)閉原始方法"?+?beanName?+?method.getName()?+?"時(shí)出現(xiàn)錯(cuò)誤");
          ????????????????}
          ????????????}
          ????????}
          ????????//最后bean保持原有返回
          ????????return?bean;
          ????}

          ????/**
          ?????*?修改注解原先的屬性
          ?????*?@param?annotation?注解實(shí)例對(duì)象
          ?????*?@throws?Exception
          ?????*/

          ????private?void?clearOriginalScheduled(Scheduled?annotation)?throws?Exception?{
          ????????changeAnnotationValue(annotation,?"cron",?Scheduled.CRON_DISABLED);
          ????????changeAnnotationValue(annotation,?"fixedDelay",?-1L);
          ????????changeAnnotationValue(annotation,?"fixedDelayString",?"");
          ????????changeAnnotationValue(annotation,?"fixedRate",?-1L);
          ????????changeAnnotationValue(annotation,?"fixedRateString",?"");
          ????????changeAnnotationValue(annotation,?"initialDelay",?-1L);
          ????????changeAnnotationValue(annotation,?"initialDelayString",?"");
          ????}


          ????/**
          ?????*?獲取SpringBoot的上下文
          ?????*?@param?applicationContext?SpringBoot的上下文
          ?????*/

          ????@Override
          ????public?void?setApplicationContext(ApplicationContext?applicationContext)?throws?BeansException?{
          ????????this.applicationContext?=?applicationContext;
          ????}
          }

          (3) 使用ApplicationRunner初始化自定義的定時(shí)任務(wù)運(yùn)行器

          • 實(shí)現(xiàn)ApplicationContextAware接口拿到SpringBoot的上下文
          • 使用@DependsOn注解強(qiáng)制依賴threadPoolTaskScheduler類
          • 實(shí)現(xiàn)ApplicationRunner接口,在所有bean初始化結(jié)束之后,運(yùn)行自定義邏輯
          • 主要實(shí)現(xiàn)邏輯在run()方法中
          @DependsOn("threadPoolTaskScheduler")
          @Component
          public?class?SuperScheduledApplicationRunner?implements?ApplicationRunner,?ApplicationContextAware?{
          ????protected?final?Log?logger?=?LogFactory.getLog(getClass());
          ????private?DateTimeFormatter?df?=?DateTimeFormatter.ofPattern("yyyy-MM-dd?HH:mm:ss");
          ????private?ApplicationContext?applicationContext;
          ?
          ?/**
          ?????*?定時(shí)任務(wù)配置管理器
          ?????*/

          ????@Autowired
          ????private?SuperScheduledConfig?superScheduledConfig;
          ????/**
          ?????*?定時(shí)任務(wù)執(zhí)行線程
          ?????*/

          ????@Autowired
          ????private?ThreadPoolTaskScheduler?threadPoolTaskScheduler;

          ????@Override
          ????public?void?run(ApplicationArguments?args)?{
          ?????//1.定時(shí)任務(wù)配置管理器中緩存??定時(shí)任務(wù)執(zhí)行線程
          ????????superScheduledConfig.setTaskScheduler(threadPoolTaskScheduler);
          ????????//2.獲取所有定時(shí)任務(wù)源數(shù)據(jù)
          ????????Map?nameToScheduledSource?=?superScheduledConfig.getNameToScheduledSource();
          ????????//逐一處理定時(shí)任務(wù)
          ????????for?(String?name?:?nameToScheduledSource.keySet())?{
          ????????????//3.獲取定時(shí)任務(wù)源數(shù)據(jù)
          ????????????ScheduledSource?scheduledSource?=?nameToScheduledSource.get(name);
          ????????????//4.獲取所有增強(qiáng)類
          ????????????String[]?baseStrengthenBeanNames?=?applicationContext.getBeanNamesForType(BaseStrengthen.class);
          ????????????//5.創(chuàng)建執(zhí)行控制器
          ????????????SuperScheduledRunnable?runnable?=?new?SuperScheduledRunnable();
          ????????????//配置執(zhí)行控制器
          ????????????runnable.setMethod(scheduledSource.getMethod());
          ????????????runnable.setBean(scheduledSource.getBean());
          ????????????//6.逐一處理增強(qiáng)類(增強(qiáng)器實(shí)現(xiàn)原理后面具體分析)
          ????????????List?points?=?new?ArrayList<>(baseStrengthenBeanNames.length);
          ????????????for?(String?baseStrengthenBeanName?:?baseStrengthenBeanNames)?{
          ?????????????//7.將增強(qiáng)器代理成point
          ????????????????Object?baseStrengthenBean?=?applicationContext.getBean(baseStrengthenBeanName);
          ????????????????//創(chuàng)建代理
          ????????????????Point?proxy?=?ProxyUtils.getInstance(Point.class,?new?RunnableBaseInterceptor(baseStrengthenBean,?runnable));
          ????????????????proxy.setSuperScheduledName(name);
          ????????????????//8.所有的points連成起來(lái)
          ????????????????points.add(proxy);
          ????????????}
          ???//將point形成調(diào)用鏈
          ????????????runnable.setChain(new?Chain(points));
          ????????????//將執(zhí)行邏輯封裝并緩存到定時(shí)任務(wù)配置管理器中
          ????????????superScheduledConfig.addRunnable(name,?runnable::invoke);
          ????????????try?{
          ?????????????//8.啟動(dòng)定時(shí)任務(wù)
          ????????????????ScheduledFuture?schedule?=?ScheduledFutureFactory.create(threadPoolTaskScheduler
          ????????????????????????,?scheduledSource,?runnable::invoke);
          ????????????????//將線程回調(diào)鉤子存到任務(wù)配置管理器中
          ????????????????superScheduledConfig.addScheduledFuture(name,?schedule);
          ????????????????logger.info(df.format(LocalDateTime.now())?+?"任務(wù)"?+?name?+?"已經(jīng)啟動(dòng)...");

          ????????????}?catch?(Exception?e)?{
          ????????????????throw?new?SuperScheduledException("任務(wù)"?+?name?+?"啟動(dòng)失敗,錯(cuò)誤信息:"?+?e.getLocalizedMessage());
          ????????????}
          ????????}
          ????}

          ????@Override
          ????public?void?setApplicationContext(ApplicationContext?applicationContext)?throws?BeansException?{
          ????????this.applicationContext?=?applicationContext;
          ????}
          }

          (4) 進(jìn)行動(dòng)態(tài)管理

          @Component
          public?class?SuperScheduledManager?{
          ????protected?final?Log?logger?=?LogFactory.getLog(getClass());
          ????private?DateTimeFormatter?df?=?DateTimeFormatter.ofPattern("yyyy-MM-dd?HH:mm:ss");

          ????@Autowired
          ????private?SuperScheduledConfig?superScheduledConfig;

          ????/**
          ?????*?修改Scheduled的執(zhí)行周期
          ?????*
          ?????*?@param?name?scheduled的名稱
          ?????*?@param?cron?cron表達(dá)式
          ?????*/

          ????public?void?setScheduledCron(String?name,?String?cron)?{
          ????????//終止原先的任務(wù)
          ????????cancelScheduled(name);
          ????????//創(chuàng)建新的任務(wù)
          ????????ScheduledSource?scheduledSource?=?superScheduledConfig.getScheduledSource(name);
          ????????scheduledSource.clear();
          ????????scheduledSource.setCron(cron);
          ????????addScheduled(name,?scheduledSource);
          ????}

          ????/**
          ?????*?修改Scheduled的fixedDelay
          ?????*
          ?????*?@param?name???????scheduled的名稱
          ?????*?@param?fixedDelay?上一次執(zhí)行完畢時(shí)間點(diǎn)之后多長(zhǎng)時(shí)間再執(zhí)行
          ?????*/

          ????public?void?setScheduledFixedDelay(String?name,?Long?fixedDelay)?{
          ????????//終止原先的任務(wù)
          ????????cancelScheduled(name);
          ????????//創(chuàng)建新的任務(wù)
          ????????ScheduledSource?scheduledSource?=?superScheduledConfig.getScheduledSource(name);
          ????????scheduledSource.clear();
          ????????scheduledSource.setFixedDelay(fixedDelay);
          ????????addScheduled(name,?scheduledSource);
          ????}

          ????/**
          ?????*?修改Scheduled的fixedRate
          ?????*
          ?????*?@param?name??????scheduled的名稱
          ?????*?@param?fixedRate?上一次開(kāi)始執(zhí)行之后多長(zhǎng)時(shí)間再執(zhí)行
          ?????*/

          ????public?void?setScheduledFixedRate(String?name,?Long?fixedRate)?{
          ????????//終止原先的任務(wù)
          ????????cancelScheduled(name);
          ????????//創(chuàng)建新的任務(wù)
          ????????ScheduledSource?scheduledSource?=?superScheduledConfig.getScheduledSource(name);
          ????????scheduledSource.clear();
          ????????scheduledSource.setFixedRate(fixedRate);
          ????????addScheduled(name,?scheduledSource);
          ????}

          ????/**
          ?????*?查詢所有啟動(dòng)的Scheduled
          ?????*/

          ????public?List?getRunScheduledName()?{
          ????????Set?names?=?superScheduledConfig.getNameToScheduledFuture().keySet();
          ????????return?new?ArrayList<>(names);
          ????}

          ????/**
          ?????*?查詢所有的Scheduled
          ?????*/

          ????public?List?getAllSuperScheduledName()?{
          ????????Set?names?=?superScheduledConfig.getNameToRunnable().keySet();
          ????????return?new?ArrayList<>(names);
          ????}

          ????/**
          ?????*?終止Scheduled
          ?????*
          ?????*?@param?name?scheduled的名稱
          ?????*/

          ????public?void?cancelScheduled(String?name)?{
          ????????ScheduledFuture?scheduledFuture?=?superScheduledConfig.getScheduledFuture(name);
          ????????scheduledFuture.cancel(true);
          ????????superScheduledConfig.removeScheduledFuture(name);
          ????????logger.info(df.format(LocalDateTime.now())?+?"任務(wù)"?+?name?+?"已經(jīng)終止...");
          ????}

          ????/**
          ?????*?啟動(dòng)Scheduled
          ?????*
          ?????*?@param?name????????????scheduled的名稱
          ?????*?@param?scheduledSource?定時(shí)任務(wù)的源信息
          ?????*/

          ????public?void?addScheduled(String?name,?ScheduledSource?scheduledSource)?{
          ????????if?(getRunScheduledName().contains(name))?{
          ????????????throw?new?SuperScheduledException("定時(shí)任務(wù)"?+?name?+?"已經(jīng)被啟動(dòng)過(guò)了");
          ????????}
          ????????if?(!scheduledSource.check())?{
          ????????????throw?new?SuperScheduledException("定時(shí)任務(wù)"?+?name?+?"源數(shù)據(jù)內(nèi)容錯(cuò)誤");
          ????????}

          ????????scheduledSource.refreshType();

          ????????Runnable?runnable?=?superScheduledConfig.getRunnable(name);
          ????????ThreadPoolTaskScheduler?taskScheduler?=?superScheduledConfig.getTaskScheduler();


          ????????ScheduledFuture?schedule?=?ScheduledFutureFactory.create(taskScheduler,?scheduledSource,?runnable);
          ????????logger.info(df.format(LocalDateTime.now())?+?"任務(wù)"?+?name?+?"已經(jīng)啟動(dòng)...");

          ????????superScheduledConfig.addScheduledSource(name,?scheduledSource);
          ????????superScheduledConfig.addScheduledFuture(name,?schedule);
          ????}

          ????/**
          ?????*?以cron類型啟動(dòng)Scheduled
          ?????*
          ?????*?@param?name?scheduled的名稱
          ?????*?@param?cron?cron表達(dá)式
          ?????*/

          ????public?void?addCronScheduled(String?name,?String?cron)?{
          ????????ScheduledSource?scheduledSource?=?new?ScheduledSource();
          ????????scheduledSource.setCron(cron);

          ????????addScheduled(name,?scheduledSource);
          ????}

          ????/**
          ?????*?以fixedDelay類型啟動(dòng)Scheduled
          ?????*
          ?????*?@param?name?????????scheduled的名稱
          ?????*?@param?fixedDelay???上一次執(zhí)行完畢時(shí)間點(diǎn)之后多長(zhǎng)時(shí)間再執(zhí)行
          ?????*?@param?initialDelay?第一次執(zhí)行的延遲時(shí)間
          ?????*/

          ????public?void?addFixedDelayScheduled(String?name,?Long?fixedDelay,?Long...?initialDelay)?{
          ????????ScheduledSource?scheduledSource?=?new?ScheduledSource();
          ????????scheduledSource.setFixedDelay(fixedDelay);
          ????????if?(initialDelay?!=?null?&&?initialDelay.length?==?1)?{
          ????????????scheduledSource.setInitialDelay(initialDelay[0]);
          ????????}?else?if?(initialDelay?!=?null?&&?initialDelay.length?>?1)?{
          ????????????throw?new?SuperScheduledException("第一次執(zhí)行的延遲時(shí)間只能傳入一個(gè)參數(shù)");
          ????????}

          ????????addScheduled(name,?scheduledSource);
          ????}

          ????/**
          ?????*?以fixedRate類型啟動(dòng)Scheduled
          ?????*
          ?????*?@param?name?????????scheduled的名稱
          ?????*?@param?fixedRate????上一次開(kāi)始執(zhí)行之后多長(zhǎng)時(shí)間再執(zhí)行
          ?????*?@param?initialDelay?第一次執(zhí)行的延遲時(shí)間
          ?????*/

          ????public?void?addFixedRateScheduled(String?name,?Long?fixedRate,?Long...?initialDelay)?{
          ????????ScheduledSource?scheduledSource?=?new?ScheduledSource();
          ????????scheduledSource.setFixedRate(fixedRate);
          ????????if?(initialDelay?!=?null?&&?initialDelay.length?==?1)?{
          ????????????scheduledSource.setInitialDelay(initialDelay[0]);
          ????????}?else?if?(initialDelay?!=?null?&&?initialDelay.length?>?1)?{
          ????????????throw?new?SuperScheduledException("第一次執(zhí)行的延遲時(shí)間只能傳入一個(gè)參數(shù)");
          ????????}

          ????????addScheduled(name,?scheduledSource);
          ????}

          ????/**
          ?????*?手動(dòng)執(zhí)行一次任務(wù)
          ?????*
          ?????*?@param?name?scheduled的名稱
          ?????*/

          ????public?void?runScheduled(String?name)?{
          ????????Runnable?runnable?=?superScheduledConfig.getRunnable(name);
          ????????runnable.run();
          ????}
          }
          2、增強(qiáng)接口實(shí)現(xiàn)

          增強(qiáng)器實(shí)現(xiàn)的整體思路與SpringAop的思路一致,實(shí)現(xiàn)沒(méi)有Aop復(fù)雜

          (1) 增強(qiáng)接口

          @Order(Ordered.HIGHEST_PRECEDENCE)
          public?interface?BaseStrengthen?{
          ????/**
          ?????*?前置強(qiáng)化方法
          ?????*
          ?????*?@param?bean???bean實(shí)例(或者是被代理的bean)
          ?????*?@param?method?執(zhí)行的方法對(duì)象
          ?????*?@param?args???方法參數(shù)
          ?????*/

          ????void?before(Object?bean,?Method?method,?Object[]?args);

          ????/**
          ?????*?后置強(qiáng)化方法
          ?????*?出現(xiàn)異常不會(huì)執(zhí)行
          ?????*?如果未出現(xiàn)異常,在afterFinally方法之后執(zhí)行
          ?????*
          ?????*?@param?bean???bean實(shí)例(或者是被代理的bean)
          ?????*?@param?method?執(zhí)行的方法對(duì)象
          ?????*?@param?args???方法參數(shù)
          ?????*/

          ????void?after(Object?bean,?Method?method,?Object[]?args);

          ????/**
          ?????*?異常強(qiáng)化方法
          ?????*
          ?????*?@param?bean???bean實(shí)例(或者是被代理的bean)
          ?????*?@param?method?執(zhí)行的方法對(duì)象
          ?????*?@param?args???方法參數(shù)
          ?????*/

          ????void?exception(Object?bean,?Method?method,?Object[]?args);

          ????/**
          ?????*?Finally強(qiáng)化方法,出現(xiàn)異常也會(huì)執(zhí)行
          ?????*
          ?????*?@param?bean???bean實(shí)例(或者是被代理的bean)
          ?????*?@param?method?執(zhí)行的方法對(duì)象
          ?????*?@param?args???方法參數(shù)
          ?????*/

          ????void?afterFinally(Object?bean,?Method?method,?Object[]?args);
          }

          (2) 代理抽象類

          public?abstract?class?Point?{
          ????/**
          ?????*?定時(shí)任務(wù)名
          ?????*/

          ????private?String?superScheduledName;

          ????/**
          ?????*?抽象的執(zhí)行方法,使用代理實(shí)現(xiàn)
          ?????*?@param?runnable?定時(shí)任務(wù)執(zhí)行器
          ?????*/

          ????public?abstract?Object?invoke(SuperScheduledRunnable?runnable);
          ????
          ????/*?普通的get/sets省略?*/
          }

          (3) 調(diào)用鏈類

          public?class?Chain?{
          ????private?List?list;
          ????private?int?index?=?-1;
          ????/**
          ?????*?索引自增1
          ?????*/

          ????public?int?incIndex()?{
          ????????return?++index;
          ????}

          ????/**
          ?????*?索引還原
          ?????*/

          ????public?void?resetIndex()?{
          ????????this.index?=?-1;
          ????}
          }

          (4) cglib動(dòng)態(tài)代理實(shí)現(xiàn)

          使用cglib代理增強(qiáng)器,將增強(qiáng)器全部代理成調(diào)用鏈節(jié)點(diǎn)Point

          public?class?RunnableBaseInterceptor?implements?MethodInterceptor?{
          ????/**
          ?????*?定時(shí)任務(wù)執(zhí)行器
          ?????*/

          ????private?SuperScheduledRunnable?runnable;
          ????/**
          ?????*?定時(shí)任務(wù)增強(qiáng)類
          ?????*/

          ????private?BaseStrengthen?strengthen;

          ????@Override
          ????public?Object?intercept(Object?obj,?Method?method,?Object[]?args,?MethodProxy?methodProxy)?throws?Throwable?{
          ????????Object?result;
          ????????//如果執(zhí)行的是invoke()方法
          ????????if?("invoke".equals(method.getName()))?{
          ?????????//前置強(qiáng)化方法
          ????????????strengthen.before(obj,?method,?args);
          ????????????try?{
          ?????????????//調(diào)用執(zhí)行器中的invoke()方法
          ????????????????result?=?runnable.invoke();
          ????????????}?catch?(Exception?e)?{
          ?????????????//異常強(qiáng)化方法
          ????????????????strengthen.exception(obj,?method,?args);
          ????????????????throw?new?SuperScheduledException(strengthen.getClass()?+?"中強(qiáng)化執(zhí)行時(shí)發(fā)生錯(cuò)誤",?e);
          ????????????}?finally?{
          ?????????????//Finally強(qiáng)化方法,出現(xiàn)異常也會(huì)執(zhí)行
          ????????????????strengthen.afterFinally(obj,?method,?args);
          ????????????}
          ????????????//后置強(qiáng)化方法
          ????????????strengthen.after(obj,?method,?args);

          ????????}?else?{
          ?????????//直接執(zhí)行方法
          ????????????result?=?methodProxy.invokeSuper(obj,?args);
          ????????}
          ????????return?result;
          ????}

          ????public?RunnableBaseInterceptor(Object?object,?SuperScheduledRunnable?runnable)?{
          ????????this.runnable?=?runnable;
          ????????if?(BaseStrengthen.class.isAssignableFrom(object.getClass()))?{
          ????????????this.strengthen?=?(BaseStrengthen)?object;
          ????????}?else?{
          ????????????throw?new?SuperScheduledException(object.getClass()?+?"對(duì)象不是BaseStrengthen類型");
          ????????}
          ????}

          ????public?RunnableBaseInterceptor()?{

          ????}
          }

          (5) 定時(shí)任務(wù)執(zhí)行器實(shí)現(xiàn)

          public?class?SuperScheduledRunnable?{
          ????/**
          ?????*?原始的方法
          ?????*/

          ????private?Method?method;
          ????/**
          ?????*?方法所在的bean
          ?????*/

          ????private?Object?bean;
          ????/**
          ?????*?增強(qiáng)器的調(diào)用鏈
          ?????*/

          ????private?Chain?chain;


          ????public?Object?invoke()?{
          ????????Object?result;
          ????????//索引自增1
          ????????if?(chain.incIndex()?==?chain.getList().size())?{
          ????????????//調(diào)用鏈中的增強(qiáng)方法已經(jīng)全部執(zhí)行結(jié)束
          ????????????try?{
          ????????????????//調(diào)用鏈索引初始化
          ????????????????chain.resetIndex();
          ????????????????//增強(qiáng)器全部執(zhí)行完畢,執(zhí)行原本的方法
          ????????????????result?=?method.invoke(bean);
          ????????????}?catch?(IllegalAccessException?|?InvocationTargetException?e)?{
          ????????????????throw?new?SuperScheduledException(e.getLocalizedMessage());
          ????????????}
          ????????}?else?{
          ????????????//獲取被代理后的方法增強(qiáng)器
          ????????????Point?point?=?chain.getList().get(chain.getIndex());
          ????????????//執(zhí)行增強(qiáng)器代理
          ????????????//增強(qiáng)器代理中,會(huì)回調(diào)方法執(zhí)行器,形成調(diào)用鏈,逐一運(yùn)行調(diào)用鏈中的增強(qiáng)器
          ????????????result?=?point.invoke(this);
          ????????}
          ????????return?result;
          ????}
          ????
          ????/*?普通的get/sets省略?*/
          }

          (6) 增強(qiáng)器代理邏輯

          com.gyx.superscheduled.core.SuperScheduledApplicationRunner類中的代碼片段

          //創(chuàng)建執(zhí)行控制器
          SuperScheduledRunnable?runnable?=?new?SuperScheduledRunnable();
          runnable.setMethod(scheduledSource.getMethod());
          runnable.setBean(scheduledSource.getBean());
          //用來(lái)存放?增強(qiáng)器的代理對(duì)象
          List?points?=?new?ArrayList<>(baseStrengthenBeanNames.length);
          //循環(huán)所有的增強(qiáng)器的beanName
          for?(String?baseStrengthenBeanName?:?baseStrengthenBeanNames)?{
          ?//獲取增強(qiáng)器的bean對(duì)象
          ????Object?baseStrengthenBean?=?applicationContext.getBean(baseStrengthenBeanName);
          ????//將增強(qiáng)器代理成Point節(jié)點(diǎn)
          ????Point?proxy?=?ProxyUtils.getInstance(Point.class,?new?RunnableBaseInterceptor(baseStrengthenBean,?runnable));
          ????proxy.setSuperScheduledName(name);
          ????//增強(qiáng)器的代理對(duì)象緩存到list中
          ????points.add(proxy);
          }
          //將增強(qiáng)器代理實(shí)例的集合生成調(diào)用鏈
          //執(zhí)行控制器中設(shè)置調(diào)用鏈
          runnable.setChain(new?Chain(points));

          來(lái)源:blog.csdn.net/qq_34886352/article/details/106494637


          1.?顏值絕絕子的 14 款 Chrome 官方主題 !

          2.?更快的Maven來(lái)了,速度提升了8倍!

          3.?12 個(gè)適合做外包項(xiàng)目的開(kāi)源后臺(tái)管理系統(tǒng)
          Java后端

          4.?面試官:說(shuō)一下 final 和 final 的 4 種用法?

          最近面試BAT,整理一份面試資料Java面試BATJ通關(guān)手冊(cè),覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫(kù)、數(shù)據(jù)結(jié)構(gòu)等等。

          獲取方式:點(diǎn)“在看”,關(guān)注公眾號(hào)并回復(fù)?Java?領(lǐng)取,更多內(nèi)容陸續(xù)奉上。

          文章有幫助的話,在看,轉(zhuǎn)發(fā)吧。

          謝謝支持喲 (*^__^*)

          瀏覽 56
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美成人自拍视频 | 骚逼综合| 免费黄色一级大片 | 欧美日韩在线视频免费播放 | 岛国爱情动作片,91,麻豆 |