最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java動態(tài)獲取實現(xiàn)類的方式詳解

 更新時間:2024年01月04日 11:08:47   作者:Java個體戶  
這篇文章主要介紹了Java動態(tài)獲取實現(xiàn)類的方式詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或工作有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧

應用場景

支付的時候,有不同的渠道,比如微信還是支付寶?

這個時候,就需要根據(jù)渠道類型,選擇走哪個渠道。

先來看下讀

/**
 * 根據(jù)接口和注解@SupportCodes的值,獲取接口實現(xiàn)類
 *
 * @param interfaceClass 接口
 * @param sopportCode 接口實現(xiàn)類的注解@SupportCodes的值
 * @return 接口實現(xiàn)類
 */
public static <T> T getServiceImpl(Class<T> interfaceClass, String sopportCode)
{
  // 如果沒有初始化,則初始化
  if (null == serviceImplFactoryMap.get(interfaceClass)) {
    // 初始化
    init(interfaceClass);
    if (null == serviceImplFactoryMap) {
      return null;
    }
  }
  // 如果初始化后,還是沒有,則返回null
  if (null == serviceImplFactoryMap.get(interfaceClass)) {
    return null;
  }
  // 返回接口實現(xiàn)類
  return (T)((Map)serviceImplFactoryMap.get(interfaceClass)).get(sopportCode);
}

為什么要先看讀?讀是需求,因為有讀的需求,才需要實現(xiàn)寫的功能。

重點來看入?yún)?,任何功能,無非是入?yún)⒑统鰠ⅰ?/p>

入?yún)ⅲ航涌诤颓来a。
出參:渠道實現(xiàn)類。

那具體怎么實現(xiàn)呢?

類似這種需求,基本上都是map。key是渠道代碼,value實現(xiàn)類。

大概的實現(xiàn)思路,基本上就是這樣。存儲用到的數(shù)據(jù)結(jié)構(gòu)是map。

剛才看了讀方法,再來看下寫。

讀,無非是從map讀。寫,也一樣,無非是把數(shù)據(jù)寫到map。

那具體怎么寫呢?直接看代碼

/**
 * 初始化
 *
 * @param interfaceClass 接口
 * @author javaself
 */
protected static <T> void init(Class<T> interfaceClass) {
  log.info("begin to init " + interfaceClass);
  synchronized (FactoryUtil.class) {
    try {
      // 如果已經(jīng)初始化,則返回
      if (null != serviceImplFactoryMap.get(interfaceClass)) {
        return;
      }
      
      Map<String, Object> serviceMap = new HashMap();
      // 獲取所有實現(xiàn)類
      Map<String, T> beans = appContext.getBeansOfType(interfaceClass); //實現(xiàn)類名字作為key,實現(xiàn)類實例作為value
      Set<Entry<String, T>> entrySet = beans.entrySet();
      Iterator<Entry<String, T>> iterator = entrySet.iterator();
      // 遍歷所有實現(xiàn)類,獲取注解@SupportCodes的值,作為key,實現(xiàn)類實例作為value
      while (iterator.hasNext()) {
        Object interfaceServiceImpl = ((Entry)iterator.next()).getValue();
        SupportCodes annotationValue = (SupportCodes)interfaceServiceImpl.getClass().getAnnotation(SupportCodes.class);
        if (null != annotationValue) {
          for (String flag : annotationValue.value()) { //可能有多個注解值,所以遍歷
            //寫到map: key=注解值,value=實現(xiàn)類實例
            serviceMap.put(flag, interfaceServiceImpl); 
            log.info(flag + "=>" + interfaceServiceImpl.getClass());
          }
        }
      }
      
      //寫到map: key=接口,value=上面的map
      serviceImplFactoryMap.put(interfaceClass, serviceMap);
    } catch (Exception e) {
      log.error("init failed", e);
      throw new RuntimeException(e);
    }
  }
  log.info(interfaceClass + "inited");
}

寫方法的入?yún)⑹牵航涌凇?/p>

也就是說,根據(jù)接口,可以獲取不同實現(xiàn)類。具體是基于spring的獲取bean的功能。

拿到不同實現(xiàn)類之后,再根據(jù)注解代碼,組裝成key/value寫到map。key是注解代碼,value是實現(xiàn)類。

注解代碼是干嘛用的?就是前面的渠道代碼。屬于業(yè)務代碼。具體是基于自定義注解實現(xiàn)。自定義注解用的時候,有幾步,首先,是自定義注解,其次,注解到類上面去,最后,讀注解的值的時候直接使用spring提供的工具類即可。

到這里其實基本上已經(jīng)寫完了,核心思路就是怎么玩弄渠道代碼和渠道實現(xiàn)類。

何時寫?

讀的時候,寫。也就是說,第一次用到的時候,寫。而不是啟動項目的時候,寫。

只需要寫一次即可,也就是說,只在第一次用到的時候,才寫。后面直接用即可。

寫的時候,注意并發(fā)問題。類似這種只寫一次,但是又需要注意并發(fā)問題的情況,一般直接使用同步關鍵字即可。

何時讀?

支付系統(tǒng)里面根據(jù)接口和渠道代碼,決定走哪個渠道實現(xiàn)類

IGetPayInstructionService payService = FactoryUtil.getServiceImpl(IGetPayInstructionService.class, channelCode);

渠道代碼的值,從哪里來?網(wǎng)關入口會判斷。具體的話,用微信還是支付寶掃碼的時候,可以根據(jù)請求頭判斷是哪個app。

完整代碼

工具類

package com.xxx.commons.factory;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.stereotype.Component;

/**
 * 工廠工具類:用于獲取接口實現(xiàn)類
 *
 * ---
 * 應用場景:當一個接口有多個實現(xiàn)類時,通過該工具類獲取對應的實現(xiàn)類。
 * 不同實現(xiàn)類,通過注解@SupportCodes來區(qū)分。獲取的時候,也是通過@SupportCodes的值來獲取。
 *
 * ---
 * 舉例說明
 *
 * 不同渠道的支付接口,都實現(xiàn)了IPayService接口,如下:微信支付、支付寶支付
 *
 * @author javaself
 */
@Component
public class FactoryUtil
  implements ApplicationContextAware
{
  private static Log log = LogFactory.getLog(FactoryUtil.class);
  private static Map<Class<?>, Map<String, Object>> serviceImplFactoryMap = new HashMap();
  private static AbstractApplicationContext appContext;

  /**
   * 根據(jù)接口和注解@SupportCodes的值,獲取接口實現(xiàn)類
   *
   * @param interfaceClass 接口
   * @param sopportCode 接口實現(xiàn)類的注解@SupportCodes的值
   * @return 接口實現(xiàn)類
   */
  public static <T> T getServiceImpl(Class<T> interfaceClass, String sopportCode)
  {
    // 如果沒有初始化,則初始化
    if (null == serviceImplFactoryMap.get(interfaceClass)) {
      // 初始化
      init(interfaceClass);
      if (null == serviceImplFactoryMap) {
        return null;
      }
    }
    // 如果初始化后,還是沒有,則返回null
    if (null == serviceImplFactoryMap.get(interfaceClass)) {
      return null;
    }
    // 返回接口實現(xiàn)類
    return (T)((Map)serviceImplFactoryMap.get(interfaceClass)).get(sopportCode);
  }

  /**
   * 初始化
   *
   * @param interfaceClass 接口
   * @author javaself
   */
  protected static <T> void init(Class<T> interfaceClass) {
    log.info("begin to init " + interfaceClass);
    synchronized (FactoryUtil.class) {
      try {
        // 如果已經(jīng)初始化,則返回
        if (null != serviceImplFactoryMap.get(interfaceClass)) {
          return;
        }

        Map<String, Object> serviceMap = new HashMap();
        // 獲取所有實現(xiàn)類
        Map<String, T> beans = appContext.getBeansOfType(interfaceClass); //實現(xiàn)類名字作為key,實現(xiàn)類實例作為value
        Set<Entry<String, T>> entrySet = beans.entrySet();
        Iterator<Entry<String, T>> iterator = entrySet.iterator();
        // 遍歷所有實現(xiàn)類,獲取注解@SupportCodes的值,作為key,實現(xiàn)類實例作為value
        while (iterator.hasNext()) {
          Object interfaceServiceImpl = ((Entry)iterator.next()).getValue();
          SupportCodes annotationValue = (SupportCodes)interfaceServiceImpl.getClass().getAnnotation(SupportCodes.class);
          if (null != annotationValue) {
            for (String flag : annotationValue.value()) { //可能有多個注解值,所以遍歷
              //寫到map: key=注解值,value=實現(xiàn)類實例
              serviceMap.put(flag, interfaceServiceImpl);
              log.info(flag + "=>" + interfaceServiceImpl.getClass());
            }
          }
        }

        //寫到map: key=接口,value=上面的map
        serviceImplFactoryMap.put(interfaceClass, serviceMap);
      } catch (Exception e) {
        log.error("init failed", e);
        throw new RuntimeException(e);
      }
    }
    log.info(interfaceClass + "inited");
  }
  
  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
  {
    appContext = (AbstractApplicationContext)applicationContext;
  }
}

注解類

package com.xxx.commons.factory;

import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({java.lang.annotation.ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface SupportCodes
{
  String[] value();
}

接口實現(xiàn)類

/**
 * 微信公眾號支付
 * 
 */
@SupportCodes("WeChatPay")
@Service
public class WeChatPayService implements IGetPayInstructionService {

以上就是Java動態(tài)獲取實現(xiàn)類的方式詳解的詳細內(nèi)容,更多關于Java動態(tài)獲取實現(xiàn)類的資料請關注腳本之家其它相關文章!

相關文章

  • SpringCloud 搭建企業(yè)級開發(fā)框架之實現(xiàn)多租戶多平臺短信通知服務(微服務實戰(zhàn))

    SpringCloud 搭建企業(yè)級開發(fā)框架之實現(xiàn)多租戶多平臺短信通知服務(微服務實戰(zhàn))

    這篇文章主要介紹了SpringCloud 搭建企業(yè)級開發(fā)框架之實現(xiàn)多租戶多平臺短信通知服務,系統(tǒng)可以支持多家云平臺提供的短信服務。這里以阿里云和騰訊云為例,集成短信通知服務,需要的朋友可以參考下
    2021-11-11
  • java使用Logback配置輸出日志內(nèi)容到文件示例代碼

    java使用Logback配置輸出日志內(nèi)容到文件示例代碼

    這篇文章主要介紹了java?Logback輸出日志內(nèi)容到文件,要將logger.info的信息輸出到文件,您可以使用Logback配置,本文通過實例代碼給大家介紹的非常詳細,需要的朋友可以參考下
    2023-09-09
  • Java 適配器模式從入門到實戰(zhàn)指南

    Java 適配器模式從入門到實戰(zhàn)指南

    這篇文章給大家介紹Java適配器模式從入門到實戰(zhàn)指南,本文從入門到實戰(zhàn),結(jié)合真實業(yè)務場景+可運行代碼+面試高頻考點,帶你吃透適配器模式,看完直接能用、能說、能面試,新手也能快速上手
    2026-04-04
  • java使用回溯法求解數(shù)獨示例

    java使用回溯法求解數(shù)獨示例

    這篇文章主要介紹了java使用回溯法求解數(shù)獨示例,大家參考使用吧
    2014-01-01
  • spring boot tomcat版本升級的實現(xiàn)示例

    spring boot tomcat版本升級的實現(xiàn)示例

    本文主要介紹了spring boot tomcat版本升級的實現(xiàn)示例,將tomcat升級一個小版本升級到9.0.44版本,文中通過圖文介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2024-11-11
  • 一篇文章帶你了解一些Java反射的學習記錄

    一篇文章帶你了解一些Java反射的學習記錄

    java反射機制是一個很好用的東西,用它可以解決很多死的東西,因為反射機制的靈活行很大,有了他,我們就不要花太多的時間來寫操做數(shù)據(jù)庫的代碼了,這個可以很大的減少開發(fā)時間,而且代碼的可讀性好
    2021-09-09
  • Java開源診斷工具Arthas使用方法詳解

    Java開源診斷工具Arthas使用方法詳解

    這篇文章主要介紹了Java開源診斷工具Arthas使用方法詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-06-06
  • spring kafka框架中@KafkaListener 注解解讀和使用案例

    spring kafka框架中@KafkaListener 注解解讀和使用案例

    Kafka 目前主要作為一個分布式的發(fā)布訂閱式的消息系統(tǒng)使用,也是目前最流行的消息隊列系統(tǒng)之一,這篇文章主要介紹了kafka @KafkaListener 注解解讀,需要的朋友可以參考下
    2023-02-02
  • Spring Security實現(xiàn)兩周內(nèi)自動登錄

    Spring Security實現(xiàn)兩周內(nèi)自動登錄"記住我"功能

    登錄過程中經(jīng)常使用的“記住我”功能,也就是我們經(jīng)常會在各種網(wǎng)站登陸時見到的"兩周內(nèi)免登錄",“三天內(nèi)免登錄”的功能。今天小編給大家分享基于Spring Security實現(xiàn)兩周內(nèi)自動登錄"記住我"功能,感興趣的朋友一起看看吧
    2019-11-11
  • ElasticSearch如何設置某個字段不分詞淺析

    ElasticSearch如何設置某個字段不分詞淺析

    最近在學習ElasticSearch官方文檔過程中發(fā)現(xiàn)的某個問題,記錄一下 希望能幫助到后面的朋友,下面這篇文章主要給大家介紹了關于ElasticSearch如何設置某個字段不分詞的相關資料,需要的朋友可以參考下
    2022-04-04

最新評論

综艺| 绥阳县| 张掖市| 高邮市| 宁国市| 南安市| 望城县| 平南县| 迭部县| 洪雅县| 石城县| 称多县| 罗江县| 苏尼特左旗| 柞水县| 红安县| 育儿| 鄢陵县| 泌阳县| 板桥市| 永定县| 扶风县| 新疆| 辽宁省| 辽中县| 郧西县| 绿春县| 新和县| 新野县| 莱阳市| 赤壁市| 南乐县| 嵩明县| 定远县| 永清县| 读书| 刚察县| 离岛区| 南充市| 天峨县| 延安市|