Ich habe eine Einzelinstanzklasse, die ExceptionMapper implementiert. Es ist keine statische Klasse, aber es ist eine Klasse, für die ich weiß, dass nur eine einzelne Instanz erstellt wird (ich habe überprüft - Konstruktor wird nur einmal aufgerufen).
Meine Klasse verwendet @Context HttpServletRequest und ich kann deutlich beobachten, dass beim Aufruf meiner ExceptionMapper.toResponse () -Methode die @Context-Anfrage < -Parameter hat einen Wert, der für eine Anforderung relevant ist, bei der die Ausnahme ausgelöst wird.
Der Doc sagt, dies ist in der Tat By-Design unterstützte Funktion und dass es mit "Proxies" gemacht wurde.
Ich frage mich, wie genau das implementiert wird - wie kann eine einzelne Instanz gleichzeitig verschiedene Membervariablenwerte haben?
Danke,
AG
P.S .: hier ist der Testcode:
%Vor%Meine REST-Handler-Methode löst eine Ausnahme aus, also wenn ich die folgenden zwei Anfragen "parallel" ausführe (der obige Schlaf sorgt dafür, dass der erste nicht fertig ist, wenn der zweite ankommt und IMHO den einzigen 'req' ändern soll) Feld):
%Vor%Mein Programm druckt:
%Vor% Die einfachste Methode, um den beobachteten Effekt zu erzielen, besteht darin, dass das injected HttpServletRequest
-Objekt tatsächlich ein Proxy-Objekt ist, ein Thread-bewusster Delegat für das real HttpServletRequest
. Wenn Sie Methoden für den Delegaten aufrufen, suchen sie nur nach dem korrekten realen Objekt (z. B. über eine lokale Threadvariable) und leiten den Aufruf an diesen weiter. Diese Strategie ist relativ einfach zu korrigieren, und da es sich um eine Schnittstelle handelt, müssen wir uns auf keinen Fall um Feldzugriffe kümmern (die für die Proxy-Erstellung etwas komplizierter sind).
Es gibt verschiedene Möglichkeiten, ein solches Proxy-Objekt zu erstellen. Insbesondere könnte dies durch direktes Implementieren der HttpServletRequest
-Schnittstelle geschehen, oder es könnte generischer über das Java-Protokoll erfolgen. generaler dynamischer Proxy-Mechanismus (der einen Proxy für jede Schnittstelle erstellen kann). Es gibt andere ausgefeiltere Möglichkeiten wie die Generierung von Laufzeitcode, aber sie sind hier nicht notwendig. OTOH, ich wäre überhaupt nicht überrascht, wenn HttpServletRequest
direkt umgesetzt wurde; es ist eine etwas wichtige Klasse für eine JAX-RS-Implementierung ...