2013-10-14 5 views
9

Das Folgende ist eine Annäherung an das Problem, das ich gegenüberstelle.Guice: So ändern Sie die Injektion zur Laufzeit basierend auf einer (dynamischen Web-Eigenschaft)

Denke, wir haben einen Passwort-Validator mit einigen Regeln.

public interface RuleChecker{ 

    //Checks for a password strenght, returns 10 
    //for strong or 0 for soft password. 
    int check(String pass); 
} 

Und dann haben wir mehrere Implementierungen, wird unser Service nur das Passwort übernehmen, wenn es mehr als 8-Score ist.

public class NoCheck implements RuleChecker { 
    public int check(String pass){return 10;} 
} 

public class LengthCheck implements RuleChecker{ 
    ... 
} 
public class AlphanumericCheck implements RuleChecker{ 
    ... 
} 
public class AlphaAndLenghtCheckAdapter implements RuleChecker{ 
    ... 
} 

aber für Testzwecke, wollen wir einen Webservice innerhalb der Anwendung implementieren, wo wir können „admin“ diese Regeln, und haben, welche davon auswählen.

public class PasswordCheckService{ 

    private RuleChecker checker; 

    @Inject 
    public PasswordCheckService(final RuleChecker checker){ 
     this.checker = checker; 
    } 

    public boolean checkPassword(String password){ 
     return checker.check(password) > 8; 
    } 
} 

Also, gibt es einen Weg in Guice, um zur Laufzeit die Injektion eines Dienstes zu ändern?

Beispiel:

Wir haben die Anwendung gestartet und wird standardmäßig LengthCheck ausgewählt und injiziert von der Anwendung auf der Website wählen wir die NoCheck Checkbox und Speicheroptionen, die in der Datenbank gespeichert ist, kann ich konfigurieren Guice zu automatisch die Bean ändern, die der Service zuvor injiziert hat? Also wird es ab jetzt keine Überprüfung neuer Passwörter geben?

-

Was jetzt habe ich diese Themen

Google Guice and varying injections at runtime gefunden, aber ich weiß nicht, ob diese Art von Anbietern mein Problem passt.

Guice runtime dependency parameters reinjection Diese nette Frage spricht etwas ähnliches, aber nicht, was ich Form suche.

guice: runtime injection/binding at command line Dies ist meinem Problem am nächsten, aber er startet nur "runtime" und ändert es nicht im Laufe der Zeit.

Irgendwelche Hilfen?

Vielen Dank!

Mit der Spitze des ersten Kommentars habe ich diese POC implementiert aber immer noch nicht funktioniert, wenn Sie ändern, wählen Sie eine andere Schaltfläche die Service-Bean ist nicht aktualisiert. https://bitbucket.org/ramonboza/guicedynamicconfig

+0

Gute Frage. Ich habe versucht, etwas sehr ähnliches zu tun. – tom

Antwort

4

Erstellen Sie einen Anbieter für jeden Feldtyp (Login, Passwort, Geburtsdatum ...), mit einem Parameter, um die Implementierung zu ändern, um zurückzukehren.

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 Ihrem Admin-Bereich ändern Sie den Wert "type", damit sich Ihre Regeln ändern. Es kann eine begrenzte Anzahl von Feldern beeinflussen, dank der Anmerkungen. Zum Beispiel: PasswordRuleCheckerProvider.setType(CheckType.LENGTH);. Wirkt nur auf Felder mit @Named('password').

Sie haben Ihre Felder und Dienstleistungen wie folgt zu erklären:

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

Ich bin gonnna machen ein PoC, um Ihre Annäherung zu versuchen;), hoffe, in ein paar Stunden zurück zu sein (Mittag Zeit jetzt xD) – RamonBoza

+0

Aktualisiert Thema, implementiert die POC ohne Glück, überprüfen Sie https://bitbucket.org/ramonboza/guicedynamicconfig – RamonBoza

+0

Verwaltet, damit es lokal funktioniert. Ich habe den Beitrag aktualisiert. Sie müssen nur Abhängigkeiten neu laden und halten Sie das Feld "type" statisch in Ihrem Provider. –