einführen
Wie wir alle wissen, ist AOP (abschnittsorientierte Programmierung) eines der Merkmale von Spring-Frameworks. AOP bietet eine extrem hohe Skalierbarkeit, indem Cross -Schneiden -Bedenken festgelegt werden. Wie funktioniert AOP im Frühjahr? Wenn Sie nur Kern -Java verwenden können, aber AOP -Technologie benötigen, wird die Antwort auf diese Frage äußerst kritisch. Darüber hinaus erscheinen solche Fragen in Interviews für fortgeschrittene technische Positionen häufig als Testfragen. Schauen Sie, mein Freund hat kürzlich ein Interview besucht und wurde eine so schwierige Frage gestellt - wie ich AOP implementieren kann, ohne Frühling und verwandte Bibliotheken zu verwenden, und nur Java. Daher werde ich in diesem Artikel einen Überblick über die Implementierung eines AOP mithilfe von Core Java bereitstellen (natürlich hat diese AOP bestimmte funktionale Einschränkungen). Beachten Sie, dass dieser Artikel keine vergleichende Untersuchung von Frühlings -AOP und Java AOP ist, sondern ein Tutorial zur Implementierung von AOP mit Hilfe von inhärenten Entwurfsmustern in Kern -Java.
Ich glaube, die Leser wissen bereits, was AOP ist und wie sie es im Spring -Framework verwenden können. Dieser Artikel konzentriert sich daher nur darauf, wie AOP ohne Spring implementiert werden kann. Zunächst müssen wir wissen, dass Spring zwei Technologien verwendet: JDK -Proxy und CGGLIB, um AOP zu implementieren. JDK Dynamic Proxy bietet eine flexible Möglichkeit, eine Methode anzuschließen und bestimmte Operationen auszuführen. Bei der Durchführung von Vorgängen muss jedoch eine Beschränkung auftreten: Eine verwandte Schnittstelle und die Implementierungsklasse der Schnittstelle müssen zuerst bereitgestellt werden. Üben Sie, um echtes Wissen zu schaffen. Lassen Sie uns diesen Satz durch einen Fall verstehen! Es gibt jetzt ein Taschenrechnerprogramm für einige mathematische Operationen. Betrachten wir die Divisionsfunktion. Die Frage zu diesem Zeitpunkt lautet: Wenn das Kernframework bereits über einen Code verfügt, um eine Abteilung zu implementieren, können wir ihn dann entführen und eine zusätzliche Überprüfung durchführen, wenn der Code ausgeführt wird? Die Antwort lautet Ja, und ich werde dies mit dem unten angegebenen Code -Snippet beweisen. Schauen wir uns zunächst den Code der grundlegenden Schnittstelle an:
öffentlicher Schnittstellenrechner {public int calculate (int a, int b);}Der Code dieser Schnittstellen -Implementierungsklasse lautet wie folgt:
public class calculatorImpl implementiert rechner {@Override public int calculate (int a, int b) {return a/b; }}Unter der Annahme, dass wir den oben genannten Code nicht reparieren oder Änderungen an der Kernbibliothek vornehmen können, wie können wir die Überprüfungsfunktion perfekt implementieren? Probieren Sie die JDK Dynamic Proxy -Funktion aus.
public class SOLHandler implementiert InvocationHandler {// Code für Einfachheit weggelassen… .. @Override öffentliches Objekt invoke (Objektproxy, Methode Methode, Objekt [] Params) löst Throwable {// Ihre komplexe Geschäftsvalidierung und Logik -Objekt -Ergebnisse = methode.invoke (targetObject, params) aus; Rückgabeergebnis; }}Lassen Sie uns sehen, wie die von JDK Dynamic Proxy implementierte Überprüfungsfunktion die Testklasse übernimmt.
public static void main (String [] args) {CalculatorImpl CalcImpl = neuer CalculatorImpl (); Taschenrechner proxied = (Taschenrechner) proxyfactory.getProxy (Rechner.Class, CalcImpl, neuer shandler (calcImpl)); int result = proxied.calculate (20, 10); System.out.println ("Endergebnis :::" + Ergebnis); }Aus den Ergebnissen können wir sehen, dass wir durch einfaches Implementieren der leistungsstarken InvocationHandler -Schnittstelle eine Hakenimplementierung erhalten können. Gemäß der JDK -Dokumentation verwendet die InvocationHandler -Schnittstelle eine Proxy -Instanz, um einen Methodenaufruf zu verarbeiten.
Jetzt wissen wir, dass die Invoke () -Methode des InvocationHandlers uns helfen kann, das Problem zu lösen. Lassen Sie uns also ein neues Problem lösen - wie können wir Vorgänge vor und nach der Methodenausführung ausführen? Um insbesondere auszudrücken, können wir eine Methode durch Hinzufügen mehrerer AOPS (vor, nach, nach, um herum) anschließen (Anmerkung des Übersetzers: Der ursprüngliche Text ist mehrere AOPs hinzu, aber ich denke, Handler fungiert als Aspekt)? Die Antwort lautet auch ja. Befolgen Sie die folgenden Schritte, um eine optimierte Codevorlage zu erstellen, um diese Anforderung zu erfüllen:
Zwei Möglichkeiten zur Implementierung von AOP:
1. Dynamische Proxy -Implementierung von JDK bereitgestellt
Schnittstelle
public interface userBean {void getUser (); void adduser (); void UpdateUser (); void DeleteUser (); } Original -Implementierungsklasse
öffentliche Klasse UserBeanImpl implementiert UserBean {private String user = null; public userBeanImpl () {} public userBeanImpl (String -Benutzer) {this.user = user; } public String getUsername () {zurückgebener Benutzer; } public void getUser () {System.out.println ("Dies ist GetUser () -Methode!"); } public void setUser (String -Benutzer) {this.user = user; System.out.println ("Dies ist setUser () -Methode!"); } public void adduser () {System.out.println ("Dies ist adduser () -Methode!"); } public void updateUser () {System.out.println ("Dies ist updateUser () -Methode!"); } public void deleteUser () {System.out.println ("Dies ist deleteUser () Methode!"); }} Agentenklasse
Import Java.lang.reflect.InvocationHandler; import Java.lang.reflect.Method; importieren java.lang.reflect.proxy; import com.cignacmc.finance.bean.userbeanimpl; öffentliche Klasse UserBeanProxy implementiert InvocationHandler {private Object targetObject; public userBeanProxy (Object targetObject) {this.targetObject = targetObject; } Public Object Invoke (Object Proxy, Methode Methode, Object [] args) löst Throwable {userBeanImpl userBean = (userBeanImpl) targetObject aus; String userername = userBean.getusername (); Objektergebnis = null; // Erlaubnisurteil if (Benutzername! = Null &&! ". } Rückgabeergebnis; }}
Testklasse
importieren java.lang.reflect.proxy; import com.cignacmc.finance.bean.userbean; import com.cignacmc.finance.bean.userbeanimpl; import com.cignacmc.finance.proxy.userbeanproxy; public class ProxyExe {public static void main (String [] args) {System.out.println ("bewiesen ........."); UserBeanImpl targetObject = new UserBeanImpl ("Bob Liang"); UserBeanProxy proxy = new UserBeanProxy (targetObject); // Proxy -Objekt userBean Object = (userBean) proxy.newproxyInstance (targetObject.getClass (). GetClassLoader (), targetObject.getClass (). GetInterfaces (), Proxy); Object.AdDuser (); System.out.println ("Nein bewiesen ............"); targetObject = new UserBeanImpl (); proxy = new UserBeanProxy (targetObject); // Proxy -Objekt Object = (userBean) proxy.newproxyInstance (targetObject.getClass (). GetClassloader (), targetObject.getClass (). GetInterfaces (), Proxy); Object.AdDuser (); }}
Ausgabe:
Bewiesen ............ Dies ist adduser () -Methode! Nein, bewiesen ..........
Aus dem obigen Beispiel kann der aufgerufene Methode adduser () erfolgreich abgefangen und entsprechend verarbeitet werden.
2. Erstellen Sie die Proxy -Klasse über CGGLIB
Der Vorteil ist, dass unser Zielobjekt nicht die Implementierung der primitiven Schnittstellenklasse erfordert.
öffentliche Klasse ClientBean {private String name = null; public ClientBean () {} public ClientBean (String -Name) {this.name = name; } public void addClient () {System.out.println ("Dies ist AddClient () -Methode!"); } public void deleteClient () {System.out.println ("Dies ist deleteClient () Methode!"); } public void getClient () {System.out.println ("Dies ist GetClient () -Methode!"); } public void getClient () {System.out.println ("Dies ist getClient ()) Methode!"); } public void updateClient () {System.out.println ("Dies ist UpdateClient () -Methode!"); } public String getClientName () {return name; } public void setClientName (String -Name) {this.name = name; }} Agentenklasse
import Java.lang.reflect.Method; com.cignacmc.finance.bean.clientbean; import net.sf.cglib.proxy.enhancer; import net.sf.cglib.proxy.methodinterceptor; import net.sf.cglib.proxy.methodinterceptor; import net.sf.cglib.proxy.methodproxy; öffentliche Klasse cglibProxy implementiert MethodInterceptor {private Object targetObject; public Object CreateReProxyObject (Object targetObject) {this.targetObject = targetObject; Enhancer Enhancer = neuer Enhancer (); Enhancer.SetsuperClass (this.targetObject.getClass ()); Enhancer.SetCallback (this); return Enhancer.create (); } public Object Intercept (Object Proxy, Method -Methode, Objekt [] args, methodProxy methodProxy) löscht Throwable {ClientBean ClientBean = (ClientBean) targetObject; String username = clientBean.getClientname (); Objektergebnis = null; if (userername! = null &&! ". } Rückgabeergebnis; }} Testklasse
importieren java.lang.reflect.proxy; com.cignacmc.finance.bean.clientbean; import com.cignacmc.finance.bean.userbean; import com.cignacmc.finance.bean.userbeanimpl; import com.cignacmc.finance.proxy.cglibproxy; import com.cignacmc.finance.proxy.userbeanproxy; public class Proxyexe {public static void main (String [] args) {System.out.println ("........ cglib proxy ............"); System.out.println ("bewiesen ..............."); Cglibproxy cproxy = new CglibProxy (); ClientBean clientBean = (ClientBean) cProxy.CreateProxyObject (New ClientBean ("Bob Liang"); ClientBean.addclient (); System.out.println ("Nein bewiesen ..............."); CProxy = new CglibProxy (); CLUPTBEAN = (CLIPLEBEAN) CProxy.CreateProxyObject (New ClientBean ()); ClientBean.addclient (); }}
Ausgabe:
..... CGGLIB Proxy .................. bewiesen ............ Dies ist addClient () -Methode! Nein, bewiesen ............