Google Guice 분석

6655 단어
최근 작업에서 Presto를 분포식 즉석 조회 엔진으로 사용했는데 그 중에서 플러그인 관련 관리는 기본적으로 Guice 주입 프레임워크를 이용하여 플러그인의 생명주기 관리를 하기 때문에 여기서 Guice를 간단하게 분석한다.
일반 클래스 설명
클래스 이름
설명
Guice
프레임 등록 포털
Injector
주입기 성명 주류
Binder
인터페이스 클래스와 실현 사이의 귀속기
Module
Binder 관계 클래스 관리 및 설정
Provider
Module의 구성 효과와 일치하는 서비스 공급자 주입
Key
provider 키 이름,spring에서 Bean의 이름과 유사하며,provider와 일대일 관계
Scope
Provider의 역할 범위
따라서 다음과 같이 간단하게 이해할 수 있다.
  • Guice는 Module의 설정에 따라 인터페이스와 실현 클래스를 귀속 관계를 구축하고 Injector에서 인터페이스와 실현 간의 Mapping 관계를 형성한다
  • Injector의 Mapping에서 Binding을 사용하여 귀속 관계를 유지합니다. 그 중에서 Key로 인터페이스를 유지합니다. (Key에는 현재 인터페이스가 지정한 실현 클래스 이름을 표시하는 Annotation 속성이 포함되어 있습니다.)Provider로 인터페이스를 유지합니다
  • injector를 통해.getInstance(XXX.class) 방식으로 인터페이스의 실례를 만들고 @inject 표시를 사용하여 완성할 수 있음
  • 실례 설명
  • 구축Module 대상
  • 일반 방식
  • import com.google.inject.AbstractModule;
    
    public class BasicModule extends AbstractModule {
    
        @Override
        protected void configure() {
            //   ILogger   LoggerImpl     
            bind(Key.get(ILogger.class, Names.named("ilogger1"))).to(LoggerImpl.class);
            bind(Key.get(ILogger.class, Names.named("ilogger2"))).to(Logger2Impl.class);
    
            //          ,      ,     Provider      
            bind(ILogger.class).annotatedWith(Names.named("ilogger1")).toProvider(new Provider() {
                @Override
                public ILogger get() {
                    return new LoggerImpl();
                }
            });
    
            //   Logger       new Logger(true) 
            bind(Logger.class).toInstance(new Logger(true));
        }
    }
    
  • 주해 방식
  • public class BasicModule extends AbstractModule {
        @Override
        protected void configure() {
            bind(Logger.class).toInstance(new Logger(true));
        }
    
        @Provides
        @Singleton
        @Named("ilogger1")
        public ILogger getILogger1() {
            return new LoggerImpl();
        }
    
        @Provides
        @Singleton
        @Named("ilogger2")
        public ILogger getILogger2() {
            return new Logger2Impl();
        }
    }
    
    public class StringModule extends AbstractModule {
    
        @Override
        protected void configure() {
            //   String       "jdbc:phoenix:localhost:2181/hbase"
            bind(String.class).annotatedWith(Names.named("url")).toInstance("jdbc:phoenix:localhost:2181/hbase");
        }
    
    }
    
    다중 실현 인터페이스 정의 및 사용 과정 중 @Named 주석을 통해 명칭 귀속을 해야 한다. 그렇지 않으면 A binding to XXX was already configured at YYY
  • 인터페이스 정의 및 그 실현
  • public interface ILogger {
        boolean log(String message);
    }
    
    public class LoggerImpl implements ILogger {
        public boolean log(String message) {
            System.out.println("Logger Message: " + message);
            return true;
        }
    }
    
    public class Logger2Impl implements ILogger {
        public boolean log(String message) {
            System.out.println("Logger2 Message: " + message);
            return true;
        }
    }
    
  • 테스트 실행
  • import com.google.inject.*;
    import com.google.inject.name.Named;
    
    import java.util.Map;
    
    public class Logger {
        private boolean hasEnabled;
    
        @Inject
        @Named("ilogger1")
        private ILogger iLogger1;
    
        @Inject
        @Named("ilogger2")
        private ILogger iLogger2;
    
        public Logger(boolean enabled) {
            if (enabled) {
                hasEnabled = enabled;
                System.out.println("Logger has enabled");
            }
        }
    
        public boolean log(String message) {
            if (hasEnabled) {
                iLogger1.log(message);
            }
            return true;
        }
    
    
        public boolean log2(String message) {
            if (hasEnabled) {
                iLogger2.log(message);
            }
            return true;
        }
    
        public static void main(String[] args) {
            //         : BasicModule   StringModule
            Injector injector = Guice.createInjector(new BasicModule(), new StringModule());
            Logger logger = injector.getInstance(Logger.class);
            String url = injector.getInstance(Key.get(String.class, Names.named("url")));
            logger.log("hello world  111");
            logger.log2("hello world  222");
            System.out.println("******" + url + "******");
            System.out.println();
    
            Map, Binding>> bindings = injector.getAllBindings();
            for (Map.Entry, Binding>> bingingEntry : bindings.entrySet()) {
                Binding binging = bingingEntry.getValue();
                Key key = binging.getKey();
                Provider provider = binging.getProvider();
                System.out.println("Key: " + key.toString());
                System.out.println("Provider: " + provider.get().getClass());
                System.out.println("************");
            }
        }
    }
    

    출력은 다음과 같습니다.
    Logger has enabled
    Logger Message: hello world  111
    Logger2 Message: hello world  222
    ******jdbc:phoenix:localhost:2181/hbase******
    
    Key: Key[type=com.google.inject.Stage, annotation=[none]]
    Provider: class com.google.inject.Stage
    ************
    Key: Key[type=com.google.inject.Injector, annotation=[none]]
    Provider: class com.google.inject.internal.InjectorImpl
    ************
    Key: Key[type=java.util.logging.Logger, annotation=[none]]
    Provider: class java.util.logging.Logger
    ************
    Key: Key[type=com.devhub.guice.Logger, annotation=[none]]
    Provider: class com.devhub.guice.Logger
    ************
    Key: Key[type=com.devhub.guice.ILogger, [email protected](value=ilogger1)]
    Provider: class com.devhub.guice.LoggerImpl
    ************
    Key: Key[type=com.devhub.guice.ILogger, [email protected](value=ilogger2)]
    Provider: class com.devhub.guice.Logger2Impl
    ************
    Key: Key[type=com.devhub.guice.Logger2Impl, annotation=[none]]
    Provider: class com.devhub.guice.Logger2Impl
    ************
    Key: Key[type=com.devhub.guice.LoggerImpl, annotation=[none]]
    Provider: class com.devhub.guice.LoggerImpl
    ************
    
    Process finished with exit code 0
    
    다중 실현 인터페이스 사용은 정의와 일치해야 하며, @Named 주석을 사용하여 명칭을 표시해야 한다. 상기 예에서 보듯이 Named에서 정의한 이름은 Key에 저장되어 서로 다른 실현을 구별한다. 상술한 바와 같이 여러 개의 모듈을 동시에 주입할 수 있고 각각의 모듈은 서로 다른 내용을 설정하여 인터페이스를 여러 가지 유형으로 실현하여 모듈의 공용을 편리하게 할 수 있다.
    Gradle 의존 라이브러리
    compile group: 'com.google.inject', name: 'guice', version: '4.2.2'
    

    참고 자료
  • guicewiki설명서
  • 좋은 웹페이지 즐겨찾기