2010-04-17 6 views

Antwort

14

Machen Sie sie nicht final. Wenn Sie AOP (einschließlich Transaktionsunterstützung) für konkrete Klassen verwenden, verwendet spring CGLIB, um Ihre Klasse dynamisch zu erweitern, um einen Proxy zu erstellen. Und die Voraussetzung für CGLIB ist, dass Ihre Klassen nicht final sind. Andernfalls wird eine Ausnahme ausgelöst.

+0

Gute Antwort. Also können DAO-Klassen "final" sein? Sie sind normalerweise nicht transaktional. – fastcodejava

+2

Nun, dann _kann_, aber sei vorsichtig damit. Sie könnten irgendwann auch etwas AOP zu ihnen hinzufügen. – Bozho

+1

Es ist ein Fehler dieser Tools, nicht in der Lage zu sein, "finale" Klassen zu instrumentieren, die ein Muss für ein korrektes OO-Design sind (siehe zum Beispiel das "Practical API Design" -Buch - oder sogar das GoF-Buch). Es gibt * Möglichkeiten, letzte Klassen zu instrumentieren; Werkzeuge wie CGLIB sind veraltet. –

4

Frühling wird ein JDK dynamischen Proxy anstatt einen CGLIB Proxy erstellen, wenn die folgenden Bedingungen erfüllt sind:

  1. aop: config hat Proxy-Ziel-Klassen auf false gesetzt
  2. jede andere Namensraum-Konfigurationen (zB tx : Transaktionsmanagement) haben auch Proxy-Ziel-Klassen auf false
  3. Ihre Klasse gesetzt implementiert eine Schnittstelle

Wenn alle drei wahr sind, dann können Sie die Klasse final deklarieren. (Sie können sogar die Klasse package-private und den Konstruktor privat machen, wenn Sie möchten, Spring kann es instanziieren).

Andernfalls erstellt Spring einen CGLIB-Proxy. Sie können die Klasse final deklarieren (vorausgesetzt, sie ist nicht mit @Repository dekoriert und Sie haben keinen PersistenceExceptionPostBeanProcessor deklariert), wenn in der Bean keine öffentlichen Methoden vorhanden sind. Sobald Sie über eine einzige öffentliche Methode verfügen, können Sie die Klasse nicht mit der CBLIB-Proxyfunktion deklarieren. (Hinweis: Sie müssen mindestens einen package-privaten Konstruktor ohne Argumente haben, wenn Sie über CGLIB per Proxy arbeiten).

Wann ist das obige nützlich? Angenommen, Sie verfügen über eine Service-Schnittstelle (alle Services sollten generell über Schnittstellen verfügen) mit einer Implementierungs-Bean, die das Paket privat ist. Der Dienst verwendet das dynamische JDK-Proxying. So kann es außerhalb des Pakets endgültig und unsichtbar sein, wodurch weniger Implementierungsdetails verloren gehen. Angenommen, der Dienst benötigt ein Datenzugriffsobjekt. Wenn kein anderer Dienst dieses DAO verwendet, warum sollten Sie es oder eine seiner Methoden veröffentlichen? Wenn alle Methoden auf dem DAO package-private sind, kann die Service-Implementierung das DAO noch verbinden und seine Methoden verwenden. Außerhalb des Pakets sehen Anrufer nur die Schnittstelle (eine gute Sache) und alle Typen, die in der Schnittstellensignatur verwendet werden.

Schließlich (kein Wortspiel beabsichtigt), machen Sie eine Klasse endgültig, wann immer Sie können. Konkrete Vererbung ist oft ein missbräuchlicher Missbrauch (siehe fragile base problem). Finale Klassen erlauben auch einige Compiler-Optimierungen.

Verwandte Themen