2013-07-23 17 views
6

heute zu finden, fanden wir dieses Muster in unserem Code:Stateful Singletons Bohnen

class Foo { 
    private List<String> errors; 

    public void addError(String error) { ... } 
    public List<String> getErrors(); 
} 

Während der Code zu funktionieren scheint, ist dies ein Singleton Spring-Bean und es ist in mehreren unabhängigen Stellen und die Verbraucher der Bohne injiziert gehe davon aus, dass sie ihre eigene Fehlerliste haben. Dies führt zu subtilen Fehlern.

Die offensichtliche Lösung ist es, Entwickler zu erziehen diese Art von Fehlern zu vermeiden, aber ich frage mich, ob es ein statisches oder Runtime-Code-Analyse-Tool ist, die diese Art von Fehlern finden können.

Zum Beispiel könnte ein Bean-Postprozessor die Bean vor der Rückgabe analysieren und nach privaten Feldern suchen, die nicht @Autowired sind.

+0

Können wir @postConstruct verwenden, um dieses private Feld zurückzusetzen? – sreeprasad

+0

@SREEPRASADGOVINDANKUTTY: Sie könnten versuchen, aber es würde nicht funktionieren, da '@ PostConstruct' würde nur einmal aufgerufen werden, wenn Foo zu schaffen. Sie können '@ PostConstruct' in Bean A nicht verwenden, um das Feld zurückzusetzen, da dies auch die Liste für Bean B löschen würde. –

+0

Obwohl es nicht eine sehr saubere Art und Weise, können Sie Feder APO versuchen, fügen Sie afterAdvice und in dieser Methode können Sie diese Felder überprüfen. –

Antwort

1

Nach etwas mehr Gehirne Gießen (unsere und andere Völker) dazu kamen wir mit diesem Ansatz auf:

  1. ein BeanPostProcessor installieren, die sicherstellt, dass alle Singleton Bohnen (also dort, wo der Umfang in der Bohne Definition ist Singleton) haben Sie die benutzerdefinierte Anmerkung @Stateless auf den tatsächlichen Bean-Typ.

    Wir haben eine benutzerdefinierte Annotation anstelle der Wiederverwendung @Singleton gewählt, da wir diese Funktionalität auch an anderer Stelle benötigen.

    Wenn die Anmerkung fehlt, gibt die Factory einen Fehler aus.

  2. In einem Komponententest verwenden wir ClassPathScanningCandidateComponentProvider ohne benutzerdefinierte Annotation, um alle Klassen auf dem Klassenpfad zu suchen. Wir können die komplexen und teure Tests dann tun, um sicherzustellen, dass die Bohne keinen Staat hat, der nach der ersten Konfiguration ändert (das heißt, nachdem der autowiring passiert ist).

Der zweite Schritt ein wenig einfacher, wenn wir die autowired Felder in den Konstruktor bewegt werden könnte, aber wir mögen Methoden nicht, dass viele nehmen, viele Argumente. Es wäre schön, wenn Java oder eine IDE Builder aus dem Bean-Code generieren könnte. Da dies nicht der Fall ist, bleiben wir bei autowired Feldern und/oder Setter.

0

Sie könnten einen JUnit-Test erstellen, der Ihre App-Konfiguration lädt. Dies könnte ListableBeanFactory kombinieren von hier:

Can I dynamically create a List by scanning the beans in a spring configuration file?

mit dem 'isSingleton' Check hier:

How to enforce a prototype scope of Spring beans

dh Liste alle Bohnen in der App Zusammenhang dann überprüfen, um zu sehen, welche sind Singletons.

Dies würden Sie alle Singleton Bohnen finden ... obwohl es nicht wirklich Ihren Fehlerfall verhindern würde, wo jemand eine dieser Singletons behandelt, als ob es nicht war.