Guice: How to change injection on runtime based on a (dynamic web property)

后端 未结 1 1457
遥遥无期
遥遥无期 2021-02-02 18:12

The following is an approximation of the problem I\'m facing.

Think we have a password validator with some rules.

public interface RuleChecker{

    //Ch         


        
相关标签:
1条回答
  • 2021-02-02 18:41

    Create a provider for each field type (login, password, birth date...), with a parameter to change the implementation to return.

    public class MyModule extends AbstractModule {
    
        public void configure() {
           bind(RuleChecker.class).annotatedWith(named("password")).toProvider(PasswordRuleCheckerProvider.class);
           bind(RuleChecker.class).annotatedWith(named("login")).toProvider(LoginRuleCheckerProvider.class);
        }
    }
    
    public static class PasswordRuleCheckerProvider implements Provider<RuleChecker> {
    
        private static CheckType type = CheckType.ALPHANUMERIC;
        // static type setter.
    
        public RuleChecker get() {
            // it would even be better if you could use singletons here.
            switch(type) {
                case LENGTH:
                    return new LengthCheck();
                case ALPHANUMERIC:
                    return new AlphanumericCheck();
                case ALPHALENGTH:
                    return new AlphaAndLenghtCheckAdapter();
                case NONE:
                default:
                    return NoCheck();
            }
        }
    }
    // Almost same provider for your LoginRuleCheckerProvider. You could do something generic.
    

    In your admin section you change "type" value, so your rules will change. It can affect a limited set of fields, thanks to the annotations. For instance : PasswordRuleCheckerProvider.setType(CheckType.LENGTH);. Will only affect fields with @Named('password').

    You have to declare your fields and services like this :

    public abstract class DynamicService {
        protected void updateService() {
            // Reinject with the new implementations the members.
            App.getInjector().injectMembers(this);
        }
    }
    
    public class PasswordCheckService extends DynamicService  {
        @Inject
        @Named("password")
        private RuleChecker passwordChecker;
    
        public void changePasswordCheckType(CheckType type) {
            PasswordRuleCheckerProvider.setType(type);
            // Reinject, so you have your new implementation.
            updateService();
        }
    
        // [...]
    }
    
    0 讨论(0)
提交回复
热议问题