5.2 dubbo - compiler 소스 코드 분석

28025 단어 자바
1         ExtensionLoader loader = ExtensionLoader.getExtensionLoader(Protocol.class);
2         final Protocol dubboProtocol = loader.getExtension("dubbo");
3         final Protocol adaptiveExtension = loader.getAdaptiveExtension();

2.2 dubbo - spi 소스 코드 해석 에서 첫 번 째 문장 을 말 했 고 제4 장 dubbo 커 널 의 op 소스 코드 해석 에서 두 번 째 문장 을 말 했 으 며 본 장 에서 마지막 문장 을 말 했다.
getAdaptive Extension () 계층 구조:
1 ExtensionLoader.getAdaptiveExtension()
2 --createAdaptiveExtension()
3 ----injectExtension(getAdaptiveExtensionClass())
4 ------getAdaptiveExtensionClass()
5 --------getExtensionClasses()// spi           @Adaptive    
6 ----------loadExtensionClasses()
7 ------------loadFile(Map> extensionClasses, String dir)
8 --------createAdaptiveExtensionClass()//   spi             @Adaptive    ,      

마지막 으로 createAdaptive ExtensionClass () 방법 을 실 행 했 습 니 다.
1     private Class> createAdaptiveExtensionClass() {
2         String code = createAdaptiveExtensionClassCode();
3         ClassLoader classLoader = findClassLoader();
4         com.alibaba.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();
5         return compiler.compile(code, classLoader);
6     }

 
구조 코드 문자열
createAdaptive ExtensionClassCode () 방법 에 서 는 클래스 에 @ Adaptive 주석 이 없 으 면 IllegalState Exception 이상 을 직접 던 집 니 다.그렇지 않 으 면 @ Adaptive 주석 이 있 는 방법 으로 코드 를 구성 하고 @ Adaptive 주석 이 없 는 방법 으로 Unsupported Operation Exception 이상 을 직접 던 집 니 다.
구 조 된 결 과 는 다음 과 같다.
 1 package com.alibaba.dubbo.rpc;
 2 
 3 import com.alibaba.dubbo.common.extension.ExtensionLoader;
 4 
 5 public class Protocol$Adaptive implements com.alibaba.dubbo.rpc.Protocol {
 6     public void destroy() {
 7         throw new UnsupportedOperationException("method public abstract void com.alibaba.dubbo.rpc.Protocol.destroy() of interface com.alibaba.dubbo.rpc.Protocol is not adaptive method!");
 8     }
 9     public int getDefaultPort() {
10         throw new UnsupportedOperationException("method public abstract int com.alibaba.dubbo.rpc.Protocol.getDefaultPort() of interface com.alibaba.dubbo.rpc.Protocol is not adaptive method!");
11     }
12     public com.alibaba.dubbo.rpc.Invoker refer(java.lang.Class arg0, com.alibaba.dubbo.common.URL arg1) throws com.alibaba.dubbo.rpc.RpcException {
13         if (arg1 == null)
14             throw new IllegalArgumentException("url == null");
15         com.alibaba.dubbo.common.URL url = arg1;
16         String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());
17         if(extName == null)
18             throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url(" + url.toString() + ") use keys([protocol])");
19         com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol)ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension(extName);
20         return extension.refer(arg0, arg1);
21     }
22     public com.alibaba.dubbo.rpc.Exporter export(com.alibaba.dubbo.rpc.Invoker arg0) throws com.alibaba.dubbo.rpc.RpcException {
23         if (arg0 == null)
24             throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument == null");
25         if (arg0.getUrl() == null)
26             throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument getUrl() == null");
27         com.alibaba.dubbo.common.URL url = arg0.getUrl();
28         String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());
29         if(extName == null)
30             throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url(" + url.toString() + ") use keys([protocol])");
31         com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol)ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension(extName);
32         return extension.export(arg0);
33     }
34 }

설명:
  • 이 생 성 류 는 dubbo 2.5.3 에서 export 와 refer 방법 성명 에서 이상 하 게 던 진 것 이 잘못 되 었 습 니 다 (dubbo 2.5.4 에서 고 쳤 습 니 다).
  • 클래스 이름 은 dubbo 2.5.4 이전 (2.5.4 포함) 도 잘못된 Protocol $Adpative, dubbo 2.5.5 로 고 쳤 습 니 다.

  •  
    컴 파 일 러 장식 클래스 가 져 오기
    com.alibaba.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();

    먼저 com. alibaba. dubbo. comon. copiler. Compiler 인 터 페 이 스 를 보 세 요.
    1 @SPI("javassist")
    2 public interface Compiler {
    3     Class> compile(String code, ClassLoader classLoader);
    4 }

    @ SPI 의 기본 값 은 javassist 입 니 다. 이전 절 경험 에 따라 기본적으로 가 져 온 Compiler 인터페이스의 실현 클래스 는 META - INF/dbo/internal/com. alibaba. dubbo. comon. copiler. Compiler 파일 의 key 는 javassit 의 실현 클래스 입 니 다.파일 내용 은 다음 과 같 습 니 다.
    1 adaptive=com.alibaba.dubbo.common.compiler.support.AdaptiveCompiler
    2 jdk=com.alibaba.dubbo.common.compiler.support.JdkCompiler
    3 javassist=com.alibaba.dubbo.common.compiler.support.JavassistCompiler

    지난 절 에 따 르 면 Extension Factory 의 getAdaptive Extension () 에 대한 설명 에 따 르 면 우리 가 최종 적 으로 얻 은 Compiler 의 Adaptive Extension 은 com. alibaba. dbo. comon. copiler. support. adaptive Compiler 가 될 것 입 니 다.
    원본 코드 를 보 려 면 먼저 ExtensionLoader loader 를 가 져 옵 니 다. 최종 loader 는 다음 과 같은 속성 을 포함 합 니 다.
  • Class> type = interface com.alibaba.dubbo.common.compiler.Compiler
  • ExtensionFactory objectFactory = AdaptiveExtensionFactory (어댑터)
  • factories = [SpringExtensionFactory 실례, SpiExtensionFactory 실례]

  • 다음은 loader. getAdaptive Extension () 입 니 다.
    이 방법 에 서 는 먼저 createAdaptive Extension () 을 호출 하여 인 스 턴 스 를 만 든 다음 캐 시 를 넣 고 되 돌려 줍 니 다.
     1     private T createAdaptiveExtension() {
     2         try {
     3             return injectExtension((T) getAdaptiveExtensionClass().newInstance());
     4         } catch (Exception e) {
     5             throw new IllegalStateException("Can not create adaptive extenstion " + type + ", cause: " + e.getMessage(),
     6                 e);
     7         }
     8     }
     9 
    10     private Class> getAdaptiveExtensionClass() {
    11         /**
    12          *   ExtensionClasses    
    13          *      cachedAdaptiveClass     ,     createAdaptiveExtensionClass()    .
    14          */
    15         getExtensionClasses();
    16         if (cachedAdaptiveClass != null) {
    17             return cachedAdaptiveClass;
    18         }
    19         return cachedAdaptiveClass = createAdaptiveExtensionClass();
    20     }

    createAdaptive Extension () 에 서 는 먼저 getAdaptive ExtensionClass () 를 호출 하여 ExtensionClasses 와 수식 류 를 가 져 온 후 수식 류 를 되 돌려 줍 니 다.META - INFO/dubbo/internal/com. alibaba. dubbo. comon. copiler. Compiler 파일 의 내용 에 따라 마지막 으로 되 돌려 줍 니 다.
  • ExtensionClasses
  • "jdk"-> "class com.alibaba.dubbo.common.compiler.support.JdkCompiler"
  • "javassist"-> "class com.alibaba.dubbo.common.compiler.support.JavassistCompiler"

  • cachedAdaptiveClass=class com.alibaba.dubbo.common.compiler.support.AdaptiveCompiler

  • 이후 Adaptive Compiler 의 무 참 구조 기 를 호출 하여 Adaptive Compiler 대상 인 스 턴 스 를 만 든 다음 inject Extension (T instance) 을 실행 하여 Adaptive Compiler 대상 인 스 턴 스 에 해당 하 는 속성 을 주입 합 니 다 (Adaptive Compiler 는 해당 하 는 setter 방법 을 제공 해 야 합 니 다). 마지막 으로 Adaptive Compiler 대상 인 스 턴 스 를 되 돌려 줍 니 다.
     
    3 번 코드 를 컴 파일 하고 class > 대상 으로 불 러 옵 니 다.
    Adaptive Compiler 대상 인 스 턴 스 를 만 든 후 다음 방법 을 실행 합 니 다.
    Class> compile(String code, ClassLoader classLoader)

    Adaptive Compiler 의 모든 원본 코드 를 보십시오.
     1 @Adaptive
     2 public class AdaptiveCompiler implements Compiler {
     3     private static volatile String DEFAULT_COMPILER;//         
     4 
     5     public static void setDefaultCompiler(String compiler) {
     6         DEFAULT_COMPILER = compiler;
     7     }
     8 
     9     /**
    10      *        ,     ,       ,             
    11      */
    12     public Class> compile(String code, ClassLoader classLoader) {
    13         Compiler compiler;
    14         ExtensionLoader loader = ExtensionLoader.getExtensionLoader(Compiler.class);
    15         String name = DEFAULT_COMPILER; // copy reference
    16         if (name != null && name.length() > 0) {
    17             compiler = loader.getExtension(name);//     name       ,          IOC AOP
    18         } else {
    19             compiler = loader.getDefaultExtension();//     JavassitCompiler,  getExtension(cachedDefaultName)
    20         }
    21         return compiler.compile(code, classLoader);//         compiler  ,              
    22     }
    23 }

    여기 서 실행 되 는 것 은 copiler = loader. getDefaultExtension () 입 니 다. 이 방법 은 말 하지 않 고 getExtension (cached DefaultName) 을 호출 하여 자바 ssistCompiler 의 인 스 턴 스 를 만 드 는 것 입 니 다.다음은 JavassistCompiler 의 copile (String code, ClassLoader classLoader) 방법 을 실행 하 는 것 입 니 다.
     1 package com.alibaba.dubbo.common.compiler.support;
     2 
     3 import com.alibaba.dubbo.common.compiler.Compiler;
     4 import com.alibaba.dubbo.common.utils.ClassHelper;
     5 
     6 import java.util.regex.Matcher;
     7 import java.util.regex.Pattern;
     8 
     9 /**
    10  * Abstract compiler. (SPI, Prototype, ThreadSafe)
    11  */
    12 public abstract class AbstractCompiler implements Compiler {
    13     private static final Pattern PACKAGE_PATTERN = Pattern.compile("package\\s+([$_a-zA-Z][$_a-zA-Z0-9\\.]*);");
    14     private static final Pattern CLASS_PATTERN = Pattern.compile("class\\s+([$_a-zA-Z][$_a-zA-Z0-9]*)\\s+");
    15 
    16     /**
    17      * 1         code        ,     
    18      * 2        Class.forName  Class>,     jvm   ,   ,    ClassNotFoundException,
    19      *     doCompile  。
    20      */
    21     public Class> compile(String code, ClassLoader classLoader) {
    22         code = code.trim();
    23         Matcher matcher = PACKAGE_PATTERN.matcher(code);
    24         String pkg;
    25         if (matcher.find()) {
    26             pkg = matcher.group(1);
    27         } else {
    28             pkg = "";
    29         }
    30         matcher = CLASS_PATTERN.matcher(code);
    31         String cls;
    32         if (matcher.find()) {
    33             cls = matcher.group(1);
    34         } else {
    35             throw new IllegalArgumentException("No such class name in " + code);
    36         }
    37         String className = pkg != null && pkg.length() > 0 ? pkg + "." + cls : cls;
    38         try {
    39             return Class.forName(className, true, ClassHelper.getCallerClassLoader(getClass()));
    40         } catch (ClassNotFoundException e) {
    41             if (!code.endsWith("}")) {
    42                 throw new IllegalStateException("The java code not endsWith \"}\", code: 
    " + code + "
    "); 43 } 44 try { 45 return doCompile(className, code); 46 } catch (RuntimeException t) { 47 throw t; 48 } catch (Throwable t) { 49 throw new IllegalStateException("Failed to compile class, cause: " + t.getMessage() + ", class: " + className + ", code:
    " + code + "
    , stack: " + ClassUtils.toString(t)); 50 } 51 } 52 } 53 54 protected abstract Class> doCompile(String name, String source) throws Throwable; 55 }

    이 방법 은 자바 ssistCompiler 의 Class > doCompile (String name, String source) 방법 을 실행 합 니 다. 이 방법 에 서 는 정규 표현 식 을 사용 하여 들 어 오 는 소스 코드 를 속성 방법 등 으로 해석 하고 자바 ssist 의 API 를 사용 하여 Class > 를 만 듭 니 다.
    마지막 으로, 이 최종 프로 토 콜 adaptiveExtension = loader. getAdaptiveExtension ();코드 가 되 돌아 오 는 adaptiveExtension = Protocol $Adaptive 인 스 턴 스.
     
    총화 (다시 한 번 잔소리):
  • ExtensionLoader. getExtensionLoader (ExtensionFactory. class). getAdaptiveExtension () 이 최종 적 으로 돌아 온 것 은: Adaptive ExtensionFactory 인 스 턴 스, 그 속성 factories = [SpringExtensionFactory 인 스 턴 스, SpiExtensionFactory 인 스 턴 스]
  • 어떤 SPI 인터페이스 (Extension Factory 제외) 를 가 져 오 든 Extension Loader 는 최종 적 으로 object Factory = 상기 Adaptive Extension Factory 인 스 턴 스
  • 가 있 을 것 입 니 다.
  • getAdaptive Extension (): 장식 클래스 나 동적 프 록 시 클래스 의 인 스 턴 스 를 가 져 오 는 역할 을 합 니 다. @ Adaptive 주해 클래스 가 있 으 면 이러한 인 스 턴 스 를 직접 되 돌려 줍 니 다. 그렇지 않 으 면 동적 프 록 시 클래스 의 인 스 턴 스 (예 를 들 어 Protocol $Adaptive 의 인 스 턴 스) 를 되 돌려 주 고 속성 주입 (dubbo - IOC) 을 완료 한 다음 인 스 턴 스 를 되 돌려 줍 니 다.
  • getExtension (String key): extensionClasses (즉 SPI 인 터 페 이 스 를 지정 한 @ Adaptive 가 없 는 구현 클래스) 에서 지정 한 key 의 extensionClass 를 가 져 오고 예화 한 다음 속성 주입 (dubbo - IOC) 을 완성 한 다음 에 dubbo - AOP 를 완성 하고 인 스 턴 스 를 되 돌려 줍 니 다.
  • 좋은 웹페이지 즐겨찾기