webentwicklung-frage-antwort-db.com.de

Initialisierung der Liste in einer JSF Managed Bean

Ich habe eine Frage zur Initialisierung von List im POJO, da der folgende Code folgt:

public class Person {

 //other fields...
 private List<String> friends=new ArrayList<>();

     public List<String> getFriends() {
        return friends;
     }
     public void setFriends(List<String> friends) {
        this.friends = friends;
    }

}

ODER ist es besser so und Initalisierung in anderen Klassen (wie zum Beispiel Bean (JSF))

public class Person {

 //other fields...
 private List<String> friends;

     public List<String> getFriends() {
        return friends;
     }
     public void setFriends(List<String> friends) {
        this.friends = friends;
    }

}

Meine Frage ist also, welcher Ansatz besser ist.

12
Mitja Rogl

Wenn es sich um eine verwaltete Bean handelt, sollten Sie dies in einer mit @PostConstruct kommentierten Methode tun.

public class Person {
    private List<String> friends;
    @PostConstruct
    public void init(){
         friends = new ArrayList<String>();
    }

    //getter and setter...
}
  1. Die Praxis, eine Initialisierung im Getter und Setter durchzuführen, wird im Rahmen der JSF im Allgemeinen missbilligt. Siehe Warum JSF Getter mehrmals anruft

  2. In per API für @PostConstruct gibt der Vertrag außerdem Sicherheitsfunktionen an und gewährleistet, dass das Bean nicht in Betrieb genommen wird, wenn eine Ausnahme in einer als solcher kommentierten Methode ausgelöst wird. Es gibt keine derartigen Garantien für einen einfachen Konstruktor.

  3. Bei einer verwalteten Bohne erfolgt die Injektion unmittelbar nach der Konstruktion. Das bedeutet, dass alle Operationen, die Sie im Konstruktor ausführen, nicht von den eingebauten Ressourcen abhängen können (über @ManagedProperty). In einer @PostConstruct-Methode haben Sie jedoch Zugriff auf alle in der verwalteten Bean deklarierten Ressourcen

BEARBEITEN: Es ist wichtig zu beachten, dass es kann nur einen geben@PostConstruct für jeden @ManagedBean, so dass alle wichtigen Initialisierungen dort stattfinden sollten. 

Es lohnt sich auch anzumerken, dass die @PostConstruct-Methode zwar der ideale Ort zum Initialisieren einer Backing-Bean-Variablen/List ist, es gibt jedoch Auswirkungen auf den Umfang der verwalteten Bean

  1. @RequestScoped: In einer verwalteten Bean mit dieser Annotation wird die Methode per Senden der betreffenden JSF-Ansicht aufgerufen. Ein @RequestScoped-Bean wird mit jeder Anforderung zerstört und neu erstellt. Dies hat zur Folge, dass die in @PostConstruct initialisierte Liste je nach Ihren Einstellungen bei jeder Anforderung auf leere Werte oder Standardwerte zurückgesetzt werden kann. Unter Umständen können Konvertierungsfehler als Folge der Neuinitialisierung der Liste mit mittlerer JSF-Anforderung auftreten.

  2. @ViewScoped: In einer verwalteten Bean mit dieser Annotation wird garantiert, dass die @PostConstruct-Methode einmal ausgeführt wird. Wenn und nur dann, wenn Sie dieselbe Instanz der @ViewScoped-Bean verwenden. Wenn das viewcoped-Bean zerstört und erneut erstellt wird, wird die @PostConstruct-Methode erneut ausgeführt.

  3. @SessionScoped: Eine Bean mit dieser Anmerkung wird einmal erstellt und bleibt am Leben, bis die HTTP-Sitzung des Benutzers endet. In diesem Szenario wird die @PostConstruct-Methode garantiert einmal und nur einmal ausgeführt, bis die Bean zerstört wird

Siehe auch

24
kolossus

Ich würde das vorschlagen:

public class Person {
     //other fields...
     private List<String> friends=new ArrayList<>();

     // returns a copy to protect original list
     public List<String> getFriends() {
        Collections.unmodifiableList(new ArrayList<>(friends));
     }
     public void addFriend(String> friend) {
        this.friends.add(friend);
     }
     public void addFriends(List<String> friends) {
        this.friends.addAll(friends);
     }
}
4
anubhava

Meiner Meinung nach ist es am besten, mit den Konstrukteuren umzugehen. Wenn ein Standardkonstruktor verwendet wird, initialisieren Sie die Liste im Konstruktor.

public Person() {
    friends = new ArrayList<>();
}

Wenn ein Konstruktor verwendet wird, der Parameter akzeptiert, lassen Sie die aufrufende Klasse in einer Liste übergeben.

public Person(ArrayList<> friends) {
    this.friends = friends;//friends
}
3
Haz

Mein Vorschlag, fügen Sie einen Null-Check im Getter hinzu:

public class Person {
  //other fields...
  private List<String> friends;

  public List<String> getFriends() {
     if (this.friends == null) friends = new ArrayList<String>();
     return friends;
  }
}

Beachte aber auch, dass ich den Setter weggelassen habe. Rufen Sie stattdessen in einem beliebigen Clientcode Folgendes auf:

personInstance.getFriends().add("Some Item");

Oder wenn Sie eine vollständige Liste zum Hinzufügen haben:

personInstance.getFriends().addAll(someStringCollection);
2
cobaltduck

Es hängt davon ab, ob. Normalerweise der erste Weg, der vorzuziehen ist, weil Sie der Sammlung später etwas hinzufügen möchten. Wenn Sie nicht wissen, ob Ihre Sammlung initialisiert wurde oder nicht, müssen Sie sie jedes Mal überprüfen.

1