Dubbo 소스 분석의 SPI 확장 메커니즘

6065 단어 #Dubbo
1. jdk spi 확장 메커니즘
1.1 spi가 뭐예요?
spi는 service provider interface로 JDK에 내장된 서비스 제공 발견 메커니즘이다.이것은 제조업체나 플러그인을 대상으로 서비스 확장을 하는 것으로 JDBC, 로그 프레임워크 등 모두 유용하다.간단하게 말하면 그것은 동적 교체 발견의 메커니즘이다.간단한 예를 들어 만약에 우리가 하나의 규범을 정의한다면 제3자 제조업체가 실현해야 한다. 그러면 우리 응용 측에 있어 대응 제조업체의 플러그인을 통합하면 대응 규범의 실현 체제를 완성할 수 있다.일종의 삽입식 확장 수단을 형성하다.
1.2 jdk spi 사양
SPI를 실현하려면 SPI 자체의 규범을 준수해야 한다.
  • 서비스 제공자는classpath에 디렉터리를 만들어야 합니다. 이 디렉터리의 이름은 META-INF/services
  • 여야 합니다.
  • 이 디렉토리에 properties 파일을 만들려면 다음 조건을 충족해야 합니다.
  • 파일 이름은 확장된 인터페이스의 전체 경로 이름이어야 합니다
  • .
  • 파일 내부에서 설명한 것은 이 확장 인터페이스의 모든 실현 클래스
  • a) 파일의 인코딩 형식은 UTF-8
  • 입니다.
  • java를 통해.util.ServiceLoader의 로딩 메커니즘을 통해 검색
  • SPI 응용 프로그램은 매우 많은데, 예를 들면 자주 사용하는common-logging 로그 인터페이스, 그리고java도 있다.sql.드라이버 드라이버는 제3자 업체가 인터페이스를 실현해야 한다.
     
    2.dubbo spi 확장 메커니즘
    두보를 이해하려면 두보의 확장 메커니즘을 이해하는 것이 필수적이다.dubbo에는 많은 확장점이 있는데 예를 들면 프로토콜 확장점Portocol, 차단기 확장점Filter, 동적 프록시 확장점ProxyFactory, 등록 센터 확장점RegistryFactory, 부하 균형 확장점LoadBance 등이 있다.dubbo는 각종 장면에 대응하기 위해 내부 구성 요소는spi 확장 메커니즘을 통해 관리한다.
    2.1 Dubbo spi 확장 규약
    Dubbo 기본 순차 검색META-INF/dubbo/internal/、META-INF/dubbo/、META-INF/services/ classpath 。 : = , k=v 。2.2 확장점 로드 클래스 ExtentionLoader
    확장 캐리어는 두보 내부의 모든 확장점의 초기화, 로드 확장 과정을 제어하는 핵심 구성 요소입니다.
      1:private static final String SERVICES_DIRECTORY = "META-INF/services/";
      2: 
      3: private static final String DUBBO_DIRECTORY = "META-INF/dubbo/";
      4: 
      5: private static final String DUBBO_INTERNAL_DIRECTORY = DUBBO_DIRECTORY + "internal/";
      6: 
      7: private static final Pattern NAME_SEPARATOR = Pattern.compile("\\s*[,]+\\s*");
      8: 
      9: // ==============================      ==============================
     10: 
     11: /**
     12:  *        
     13:  *
     14:  * key:    
     15:  */
     16: private static final ConcurrentMap, ExtensionLoader>> EXTENSION_LOADERS = new ConcurrentHashMap, ExtensionLoader>>();
     17: /**
     18:  *        
     19:  *
     20:  * key:     
     21:  * value:    。
     22:  *
     23:  *   ,key   Class
     24:  *  value   AccessLogFilter   
     25:  */
     26: private static final ConcurrentMap, Object> EXTENSION_INSTANCES = new ConcurrentHashMap, Object>();
     27: 
     28: // ==============================      ==============================
     29: 
     30: /**
     31:  *     。
     32:  *   ,Protocol
     33:  */
     34: private final Class> type;
     35: /**
     36:  *     
     37:  *
     38:  *      {@link #injectExtension(Object)}   ,           。
     39:  *
     40:  *   ,StubProxyFactoryWrapper    `Protocol protocol`   。
     41:  */
     42: private final ExtensionFactory objectFactory;
     43: /**
     44:  *              。
     45:  *
     46:  *   {@link #cachedClasses}   KV   。
     47:  *
     48:  *    {@link #loadExtensionClasses}   
     49:  */
     50: private final ConcurrentMap, String> cachedNames = new ConcurrentHashMap, String>();
     51: /**
     52:  *           。
     53:  *
     54:  *          :
     55:  *  1.         。   AdaptiveExtensionFactory
     56:  *  2.                    ,      Wrapper    。  ,ProtocolFilterWrapper 。
     57:  *      Wrapper    ,     {@link #cachedWrapperClasses}  
     58:  *
     59:  *    {@link #loadExtensionClasses}   
     60:  */
     61: private final Holder>> cachedClasses = new Holder>>();
     62: 
     63: /**
     64:  *      @Activate    
     65:  *
     66:  *   ,AccessLogFilter。
     67:  *
     68:  *    {@link #getActivateExtension(URL, String)}
     69:  */
     70: private final Map cachedActivates = new ConcurrentHashMap();
     71: /**
     72:  *          
     73:  *
     74:  * key:   
     75:  * value:    
     76:  *
     77:  *   ,Protocol   
     78:  *      key:dubbo value:DubboProtocol
     79:  *      key:injvm value:InjvmProtocol
     80:  *
     81:  *    {@link #loadExtensionClasses}   
     82:  */
     83: private final ConcurrentMap> cachedInstances = new ConcurrentHashMap>();
     84: /**
     85:  *       ( Adaptive )    
     86:  */
     87: private final Holder cachedAdaptiveInstance = new Holder();
     88: /**
     89:  *             
     90:  *
     91:  * {@link #getAdaptiveExtensionClass()}
     92:  */
     93: private volatile Class> cachedAdaptiveClass = null;
     94: /**
     95:  *         
     96:  *
     97:  *    {@link SPI}     
     98:  */
     99: private String cachedDefaultName;
    100: /**
    101:  *    {@link #cachedAdaptiveInstance}       。
    102:  *
    103:  *      ,    ,   {@link #createAdaptiveExtension()}
    104:  */
    105: private volatile Throwable createAdaptiveInstanceError;
    106: 
    107: /**
    108:  *    Wrapper      
    109:  *
    110:  *                    
    111:  *
    112:  *    {@link #loadExtensionClasses}   
    113:  */
    114: private Set> cachedWrapperClasses;
    115: 
    116: /**
    117:  *                        
    118:  *
    119:  * key:   
    120:  * value:  
    121:  *
    122:  *   {@link #loadFile(Map, String)}  ,  
    123:  */
    124: private Map exceptions = new ConcurrentHashMap();

    @SPI, @Adaptive, @Activate 역할 @SPI(주석은 클래스에 있음): @SPI 주석은 인터페이스가 확장점임을 표시하고 속성value는 기본적으로 적합한 확장점의 이름을 지정하는 데 사용됩니다.
    @Activate (주해는 유형과 방법에 있음): @Activate 주해는 확장점의 실현 클래스에서 확장 클래스가 가져온 조건을 표시합니다. 조건에 부합되면 가져오고, 조건에 부합되지 않으면 가져오지 않습니다. @Activate의 그룹,value 속성에 따라 필터합니다.구체적으로 ExtensionLoader의 getActivateExtension 함수를 참조합니다.
    @Adaptive (주석은 종류와 방법에 있음): @Adaptive 주석은 클래스에 있습니다. 이 클래스는 기본적으로 적당한 확장입니다. @Adaptive 주석이 확장점 Interface 방법에 있을 때, dubbo는 이 확장점의 적합한 확장 클래스 (코드 생성, 동적 컴파일 실례화 클래스) 를 동적으로 생성합니다. 이름은 확장점 Interface의 간단한 클래스 이름 + $Adaptive, 예를 들어 ProxyFactory$Adpative 입니다.이렇게 하는 목적은 실행할 때 서로 다른 확장 실례를 맞추기 위해서이다. 실행할 때 전송된 URL 형식의 매개 변수나 내부에 URL 방법을 가져오는 매개 변수가 포함되어 있으며, URL에서 사용할 확장 클래스의 이름을 가져오고, 이름에 따라 대응하는 확장 사례를 불러오기 위해서이다. 이 확장 실례 대상으로 같은 방법을 호출하기 위해서다.런타임 시 런타임에 적합한 확장 인스턴스가 없으면 @SPI 메모를 사용하여 기본적으로 지정된 확장을 사용합니다.이런 방식을 통해 운행할 때 대응하는 확장을 실현하였다.

    좋은 웹페이지 즐겨찾기