Guice inject based on annotation value

前端 未结 2 1457
孤独总比滥情好
孤独总比滥情好 2021-01-12 17:43

I would like to use goolge/guice inject a value based on a class i provide with the annotation.

AutoConfig annotation

@BindingAnnotation
@Retention(R         


        
2条回答
  •  挽巷
    挽巷 (楼主)
    2021-01-12 18:48

    I had a similar problem. I wanted to use a custom annotation that receives a enum param to choose the implementation. After a lot of research, debug and testing, I came to the following solution:

    //enum to define authentication types
    public enum AuthType {
        Ldap, Saml
    }
    
    //custom annotation to be used in injection
    @Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
    @BindingAnnotation
    public @interface Auth {
        AuthType value();
    }
    
    //defintion of authenticator
    public interface Authenticator {
        public void doSomehting();
    }
    
    
    //Authenticator implementations 
    public class LdapAuthenticator implements Authenticator {
    
        @Override
        public void doSomehting() {
            // doing ldap stuff
        }
    
    }
    
    public class SamlAuthenticator implements Authenticator {
    
        @Override
        public void doSomehting() {
            // doing saml stuff
        }
    
    }
    
    public class MyModule extends AbstractModule {
    
        // annotate fields to bind to implementations
        private @Auth(AuthType.Ldap) Authenticator ldap;
        private @Auth(AuthType.Saml) Authenticator saml;
    
        @Override
        protected void configure() {
            //bind the implementation to the annotation from field
            bindAnnotated("ldap", LdapAuthenticator.class);
            bindAnnotated("saml", SamlAuthenticator.class);
    
        }
    
        private void bindAnnotated(String fieldName, Class implementation) {
            try {
                //get the annotation from fields, then bind it to implementation                
                Annotation ann = MyModule.class.getDeclaredField(fieldName).getAnnotation(Auth.class);
                bind(Authenticator.class).annotatedWith(ann).to(implementation);
            } catch (NoSuchFieldException | SecurityException e) {
                throw new RuntimeException(e);
            }
        }
    }
    
    
    //usage:  add @Auth() to the dependency
    
    public class ClientClass {
    
        private Authenticator authenticator;
    
        @Inject
        public ClientClass(@Auth(AuthType.Ldap) Authenticator authenticator) {
            this.authenticator = authenticator;
        }
    }
    

    Check the documentation of Binder

    I tested the Jeff Bowman solution, but it apparently works only binding to providers

提交回复
热议问题