Spring Framework basiert auf zwei grundlegenden Konzepten – Dependency Injection und Aspect Oriented Programming (Spring AOP).
Spring AOP
Wir haben bereits gesehen, wie Spring Dependency Injection funktioniert. Heute werden wir uns die Kernkonzepte der aspektorientierten Programmierung ansehen und wie wir sie mithilfe des Spring Frameworks implementieren können.
Überblick über Spring AOP
Die meisten Unternehmensanwendungen haben gemeinsame übergreifende Anliegen, die auf verschiedene Arten von Objekten und Modulen anwendbar sind. Einige der gemeinsamen übergreifenden Anliegen sind Protokollierung, Transaktionsverwaltung, Datenvalidierung usw. In der objektorientierten Programmierung wird die Modularität der Anwendung durch Klassen erreicht, während in der aspektorientierten Programmierung die Modularität der Anwendung durch Aspekte erreicht wird und sie so konfiguriert sind, dass sie verschiedene Klassen überschneiden. Spring AOP entfernt die direkte Abhängigkeit von übergreifenden Aufgaben von Klassen, die wir nicht durch das normale objektorientierte Programmiermodell erreichen können. Zum Beispiel können wir eine separate Klasse für die Protokollierung haben, aber die funktionalen Klassen müssen diese Methoden wieder aufrufen, um eine Protokollierung über die Anwendung hinweg zu erreichen.
Grundkonzepte der aspektorientierten Programmierung
Bevor wir in die Implementierung der Spring AOP-Implementierung eintauchen, sollten wir die Kernkonzepte von AOP verstehen.
- Aspekt: Ein Aspekt ist eine Klasse, die Unternehmensanliegen implementiert, die sich über mehrere Klassen erstrecken, wie z. B. die Transaktionsverwaltung. Aspekte können eine normale Klasse sein, die über die Spring-XML-Konfiguration konfiguriert ist, oder wir können die Spring AspectJ-Integration verwenden, um eine Klasse als Aspekt zu definieren, die die
@Aspect
-Annotation verwendet. - Verbindungspunkt: Ein Verbindungspunkt ist ein bestimmter Punkt in der Anwendung wie Methodenausführung, Ausnahmebehandlung, Ändern von Objektvariablenwerten usw. In Spring AOP ist ein Verbindungspunkt immer die Ausführung einer Methode.
- Ratschlag: Ratschläge sind Aktionen, die für einen bestimmten Verbindungspunkt ausgeführt werden. In programmtechnischer Hinsicht handelt es sich dabei um Methoden, die ausgeführt werden, wenn ein bestimmter Verbindungspunkt mit übereinstimmendem Pointcut in der Anwendung erreicht wird. Sie können Ratschläge als Struts2-Interceptor oder Servlet-Filter betrachten.
- Pointcut: Ein Pointcut sind Ausdrücke, die mit Verbindungspunkten übereinstimmen, um festzustellen, ob ein Ratschlag ausgeführt werden muss oder nicht. Pointcut verwendet verschiedene Arten von Ausdrücken, die mit den Verbindungspunkten übereinstimmen, und das Spring-Framework verwendet die AspectJ-Punktcut-Ausdruckssprache.
- Zielobjekt: Dies sind die Objekte, auf die Ratschläge angewendet werden. Spring AOP wird mit Laufzeitproxys implementiert, sodass dieses Objekt immer ein proxiiertes Objekt ist. Das bedeutet, dass zur Laufzeit eine Unterklasse erstellt wird, in der die Zielmethode überschrieben und Ratschläge basierend auf ihrer Konfiguration einbezogen werden.
- AOP-Proxy: Die Spring-AOP-Implementierung verwendet den JDK-Dynamik-Proxy, um die Proxy-Klassen mit Zielklassen und Ratsaufrufen zu erstellen. Diese werden als AOP-Proxy-Klassen bezeichnet. Wir können auch den CGLIB-Proxy verwenden, indem wir ihn als Abhängigkeit im Spring-AOP-Projekt hinzufügen.
- Weben: Dies ist der Prozess, Aspekte mit anderen Objekten zu verknüpfen, um die beratenen Proxy-Objekte zu erstellen. Dies kann zur Compilezeit, zur Ladezeit oder zur Laufzeit erfolgen. Spring AOP führt das Weben zur Laufzeit durch.
AOP-Ratschläge
Basierend auf der Ausführungsstrategie des Rats sind sie folgendermaßen.
- Vorheriger Ratschlag: Diese Ratschläge werden vor der Ausführung der Verbindungspunktmethoden ausgeführt. Wir können die Annotation
@Before
verwenden, um einen Ratschlagstyp als Vorherigen Ratschlag zu markieren. - Nach (endlich) Ratschlag: Ein Ratschlag, der ausgeführt wird, nachdem die Verbindungspunkt-Methode ihre Ausführung beendet hat, sei es normal oder durch Werfen einer Ausnahme. Wir können einen Nachratschlag mit der Annotation
@After
erstellen. - Nach Rückkehr-Ratschlag: Manchmal möchten wir, dass Ratschläge nur ausgeführt werden, wenn die Verbindungspunkt-Methode normal ausgeführt wird. Wir können die Annotation
@AfterReturning
verwenden, um eine Methode als Nach Rückkehr-Ratschlag zu markieren. - Nach dem Geben von Ratschlägen: Dieser Ratschlag wird nur ausgeführt, wenn die Join-Point-Methode eine Ausnahme wirft. Wir können ihn verwenden, um die Transaktion deklarativ zurückzurollen. Wir verwenden die
@AfterThrowing
-Annotation für diese Art von Ratschlag. - Um-Ratschlag: Dies ist der wichtigste und mächtigste Ratschlag. Dieser Ratschlag umgibt die Join-Point-Methode, und wir können auch wählen, ob die Join-Point-Methode ausgeführt werden soll oder nicht. Wir können Ratschlagscode schreiben, der vor und nach der Ausführung der Join-Point-Methode ausgeführt wird. Es liegt in der Verantwortung des Um-Ratschlags, die Join-Point-Methode aufzurufen und Werte zurückzugeben, wenn die Methode etwas zurückgibt. Wir verwenden die
@Around
-Annotation, um Um-Ratschlagsmethoden zu erstellen.
Die oben genannten Punkte mögen verwirrend klingen, aber wenn wir die Implementierung von Spring AOP betrachten, werden die Dinge klarer. Lassen Sie uns damit beginnen, ein einfaches Spring-Projekt mit AOP-Implementierungen zu erstellen. Spring bietet Unterstützung für die Verwendung von AspectJ-Annotationen zur Erstellung von Aspekten, und wir werden das für die Einfachheit verwenden. Alle oben genannten AOP-Annotationen sind im Paket org.aspectj.lang.annotation
definiert. Spring Tool Suite bietet nützliche Informationen über die Aspekte, daher würde ich empfehlen, es zu verwenden. Wenn Sie mit STS nicht vertraut sind, empfehle ich Ihnen, einen Blick auf das Spring MVC Tutorial zu werfen, in dem ich erkläre, wie man es verwendet.
Spring AOP Beispiel
Erstellen Sie ein neues einfaches Spring-Maven-Projekt, sodass alle Spring Core-Bibliotheken in den pom.xml-Dateien enthalten sind und wir sie nicht explizit einbeziehen müssen. Unser endgültiges Projekt wird wie auf dem untenstehenden Bild aussehen, wir werden die Spring-Core-Komponenten und Aspektimplementierungen im Detail betrachten.
Spring AOP AspectJ-Abhängigkeiten
Das Spring-Framework bietet standardmäßig Unterstützung für AOP, aber da wir AspectJ-Annotationen zur Konfiguration von Aspekten und Ratschlägen verwenden, müssen wir sie in die pom.xml-Datei aufnehmen.
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.samples</groupId>
<artifactId>SpringAOPExample</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<!-- Generic properties -->
<java.version>1.6</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<!-- Spring -->
<spring-framework.version>4.0.2.RELEASE</spring-framework.version>
<!-- Logging -->
<logback.version>1.0.13</logback.version>
<slf4j.version>1.7.5</slf4j.version>
<!-- Test -->
<junit.version>4.11</junit.version>
<!-- AspectJ -->
<aspectj.version>1.7.4</aspectj.version>
</properties>
<dependencies>
<!-- Spring and Transactions -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<!-- Logging with SLF4J & LogBack -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
<scope>runtime</scope>
</dependency>
<!-- AspectJ dependencies -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
</project>
Beachten Sie, dass ich die Abhängigkeiten aspectjrt
und aspectjtools
(Version 1.7.4) im Projekt hinzugefügt habe. Außerdem habe ich die Spring-Framework-Version auf die neueste Version aktualisiert, d. h. 4.0.2.RELEASE.
Modellklasse
Erstellen wir eine einfache Java-Bean, die wir für unser Beispiel mit einigen zusätzlichen Methoden verwenden werden. Employee.java-Code:
package com.journaldev.spring.model;
import com.journaldev.spring.aspect.Loggable;
public class Employee {
private String name;
public String getName() {
return name;
}
@Loggable
public void setName(String nm) {
this.name=nm;
}
public void throwException(){
throw new RuntimeException("Dummy Exception");
}
}
Hast du bemerkt, dass die Methode setName() mit der Loggable
-Annotation versehen ist? Es handelt sich um eine benutzerdefinierte Java-Annotation, die wir im Projekt definiert haben. Wir werden uns später mit ihrer Verwendung befassen.
Service-Klasse
Lasst uns eine Service-Klasse erstellen, um mit dem Employee-Bean zu arbeiten. Der Code für EmployeeService.java lautet:
package com.journaldev.spring.service;
import com.journaldev.spring.model.Employee;
public class EmployeeService {
private Employee employee;
public Employee getEmployee(){
return this.employee;
}
public void setEmployee(Employee e){
this.employee=e;
}
}
I could have used Spring annotations to configure it as a Spring Component, but we will use XML based configuration in this project. EmployeeService class is very standard and just provides us an access point for Employee beans.
Spring-Bean-Konfiguration mit AOP
Wenn du STS verwendest, hast du die Möglichkeit, eine „Spring Bean-Konfigurationsdatei“ zu erstellen und das AOP-Schema-Namespace auszuwählen. Wenn du jedoch eine andere IDE verwendest, kannst du es einfach in die Spring-Bean-Konfigurationsdatei einfügen. Meine Projekt-Bean-Konfigurationsdatei sieht wie folgt aus: spring.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="https://www.springframework.org/schema/aop"
xsi:schemaLocation="https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans-4.0.xsd
https://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
<!-- Enable AspectJ style of Spring AOP -->
<aop:aspectj-autoproxy />
<!-- Configure Employee Bean and initialize it -->
<bean name="employee" class="com.journaldev.spring.model.Employee">
<property name="name" value="Dummy Name"></property>
</bean>
<!-- Configure EmployeeService bean -->
<bean name="employeeService" class="com.journaldev.spring.service.EmployeeService">
<property name="employee" ref="employee"></property>
</bean>
<!-- Configure Aspect Beans, without this Aspects advices wont execute -->
<bean name="employeeAspect" class="com.journaldev.spring.aspect.EmployeeAspect" />
<bean name="employeeAspectPointcut" class="com.journaldev.spring.aspect.EmployeeAspectPointcut" />
<bean name="employeeAspectJoinPoint" class="com.journaldev.spring.aspect.EmployeeAspectJoinPoint" />
<bean name="employeeAfterAspect" class="com.journaldev.spring.aspect.EmployeeAfterAspect" />
<bean name="employeeAroundAspect" class="com.journaldev.spring.aspect.EmployeeAroundAspect" />
<bean name="employeeAnnotationAspect" class="com.journaldev.spring.aspect.EmployeeAnnotationAspect" />
</beans>
Um Spring AOP in Spring-Beans zu verwenden, müssen wir Folgendes tun:
- Erkläre den AOP-Namespace wie xmlns:aop=“https://www.springframework.org/schema/aop„
- Füge das aop:aspectj-autoproxy-Element hinzu, um die Unterstützung von Spring AspectJ mit automatischem Proxy zur Laufzeit zu aktivieren
- Konfiguriere Aspektklassen wie andere Spring-Beans
Sie können sehen, dass ich viele Aspekte in der Spring-Bean-Konfigurationsdatei definiert habe, es ist Zeit, sie nacheinander zu untersuchen.
Spring AOP Before Aspect Beispiel
EmployeeAspect.java-Code:
package com.journaldev.spring.aspect;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class EmployeeAspect {
@Before("execution(public String getName())")
public void getNameAdvice(){
System.out.println("Executing Advice on getName()");
}
@Before("execution(* com.journaldev.spring.service.*.get*())")
public void getAllAdvice(){
System.out.println("Service method getter called");
}
}
Wichtige Punkte in der obigen Aspektklasse sind:
- Aspekt Klassen müssen die Annotation
@Aspect
haben. - @Before Annotation wird verwendet, um vorherigen Rat zu erstellen
- Der Zeichenfolgenparameter, der in der
@Before
-Annotation übergeben wird, ist der Pointcut-Ausdruck - getNameAdvice() Ratschlag wird für jede Spring Bean-Methode mit Signatur
public String getName()
ausgeführt. Dies ist ein sehr wichtiger Punkt zu beachten, wenn wir den Employee-Bean mit dem neuen Operator erstellen, werden die Ratschläge nicht angewendet. Nur wenn wir ApplicationContext verwenden, um die Bean zu erhalten, werden Ratschläge angewendet. - Wir können ein Asterisk (*) als Joker in Pointcut-Ausdrücken verwenden, getAllAdvice() wird für alle Klassen im Paket
com.journaldev.spring.service
angewendet, deren Name mitget
beginnt und keine Argumente akzeptiert.
Wir werden uns den Ratschlag in Aktion in einer Testklasse ansehen, nachdem wir uns alle verschiedenen Arten von Ratschlägen angesehen haben.
Spring AOP Pointcut Methoden und Wiederverwendung
Manchmal müssen wir denselben Pointcut-Ausdruck an mehreren Stellen verwenden. Wir können eine leere Methode mit der @Pointcut
-Annotation erstellen und sie dann als Ausdruck in den Advices verwenden. EmployeeAspectPointcut.java-Code:
package com.journaldev.spring.aspect;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class EmployeeAspectPointcut {
@Before("getNamePointcut()")
public void loggingAdvice(){
System.out.println("Executing loggingAdvice on getName()");
}
@Before("getNamePointcut()")
public void secondAdvice(){
System.out.println("Executing secondAdvice on getName()");
}
@Pointcut("execution(public String getName())")
public void getNamePointcut(){}
@Before("allMethodsPointcut()")
public void allServiceMethodsAdvice(){
System.out.println("Before executing service method");
}
//Pointcut, der auf alle Methoden von Klassen in einem Paket angewendet wird
@Pointcut("within(com.journaldev.spring.service.*)")
public void allMethodsPointcut(){}
}
Das obige Beispiel ist sehr klar, anstatt des Ausdrucks verwenden wir den Methodennamen im Argument der Advice-Annotation.
Spring AOP JoinPoint und Advice-Argumente
Wir können JoinPoint als Parameter in den Advice-Methoden verwenden und damit die Methodensignatur oder das Zielobjekt erhalten. Wir können den args()
-Ausdruck im Pointcut verwenden, um auf jede Methode angewendet zu werden, die zum Argumentmuster passt. Wenn wir dies verwenden, müssen wir denselben Namen in der Advice-Methode verwenden, aus der der Argumenttyp bestimmt wird. Wir können auch generische Objekte in den Advice-Argumenten verwenden. EmployeeAspectJoinPoint.java-Code:
package com.journaldev.spring.aspect;
import java.util.Arrays;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class EmployeeAspectJoinPoint {
@Before("execution(public void com.journaldev.spring.model..set*(*))")
public void loggingAdvice(JoinPoint joinPoint){
System.out.println("Before running loggingAdvice on method="+joinPoint.toString());
System.out.println("Agruments Passed=" + Arrays.toString(joinPoint.getArgs()));
}
//Advice-Argumente, die auf Bean-Methoden mit einem einzigen String-Argument angewendet werden
@Before("args(name)")
public void logStringArguments(String name){
System.out.println("String argument passed="+name);
}
}
Spring AOP Nachberatungsbeispiel
Lassen Sie uns eine einfache Aspektklasse mit einem Beispiel für die Nach-, Nachwurf- und Rückgabeberatung betrachten. MitarbeiterAfterAspect.java-Code:
package com.journaldev.spring.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class EmployeeAfterAspect {
@After("args(name)")
public void logStringArguments(String name){
System.out.println("Running After Advice. String argument passed="+name);
}
@AfterThrowing("within(com.journaldev.spring.model.Employee)")
public void logExceptions(JoinPoint joinPoint){
System.out.println("Exception thrown in Employee Method="+joinPoint.toString());
}
@AfterReturning(pointcut="execution(* getName())", returning="returnString")
public void getNameReturningAdvice(String returnString){
System.out.println("getNameReturningAdvice executed. Returned String="+returnString);
}
}
Wir können innerhalb
im Pointcut-Ausdruck verwenden, um den Ratschlag auf alle Methoden in der Klasse anzuwenden. Wir können den Ratschlag @AfterReturning verwenden, um das Objekt zurückzugeben, das von der beratenen Methode zurückgegeben wird. Wir haben die Methode throwException() im Mitarbeiter-Bean, um die Verwendung der Nachwurfberatung zu demonstrieren.
Spring AOP Around-Aspektbeispiel
Wie bereits erläutert, können wir den Um-Aspekt verwenden, um die Methodenausführung vorher und nachher zu unterbrechen. Wir können es verwenden, um zu steuern, ob die beratene Methode ausgeführt wird oder nicht. Wir können auch den zurückgegebenen Wert überprüfen und ändern. Dies ist der leistungsstärkste Ratschlag und muss ordnungsgemäß angewendet werden. MitarbeiterAroundAspect.java-Code:
package com.journaldev.spring.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class EmployeeAroundAspect {
@Around("execution(* com.journaldev.spring.model.Employee.getName())")
public Object employeeAroundAdvice(ProceedingJoinPoint proceedingJoinPoint){
System.out.println("Before invoking getName() method");
Object value = null;
try {
value = proceedingJoinPoint.proceed();
} catch (Throwable e) {
e.printStackTrace();
}
System.out.println("After invoking getName() method. Return value="+value);
return value;
}
}
Um einen Rat herum wird immer ein ProceedingJoinPoint als Argument benötigt, und wir sollten seine proceed() -Methode verwenden, um die Methode des Zielobjekts aufzurufen, die beraten wurde. Wenn die beratene Methode etwas zurückgibt, liegt es in der Verantwortung des Rats, es an das aufrufende Programm zurückzugeben. Für void-Methoden kann die Ratsmethode null zurückgeben. Da der umgebende Rat um die beratene Methode geschnitten wird, können wir sowohl die Eingabe und Ausgabe der Methode als auch ihr Ausführungsverhalten kontrollieren.
Spring-Rat mit benutzerdefiniertem Annotation-Pointcut
Wenn Sie sich alle oben genannten Ratschläge für Schnittpunktausdrücke ansehen, besteht die Möglichkeit, dass sie auf einige andere Beans angewendet werden, wo es nicht beabsichtigt ist. Zum Beispiel kann jemand eine neue Spring-Bohne mit der getName() Methode definieren und der Ratschlag wird beginnen, darauf angewendet zu werden, obwohl es nicht beabsichtigt war. Deshalb sollten wir den Anwendungsbereich des Schnittpunktausdrucks so eng wie möglich halten. Ein alternativer Ansatz besteht darin, eine benutzerdefinierte Annotation zu erstellen und die Methoden zu kennzeichnen, auf die wir den Ratschlag anwenden möchten. Dies ist der Zweck des Employee setName() Methode, die mit der @Loggable Annotation versehen ist. Die Spring Framework @Transactional Annotation ist ein großartiges Beispiel für diesen Ansatz für das Spring-Transaktionsmanagement. Loggable.java Code:
package com.journaldev.spring.aspect;
public @interface Loggable {
}
EmployeeAnnotationAspect.java Code:
package com.journaldev.spring.aspect;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class EmployeeAnnotationAspect {
@Before("@annotation(com.journaldev.spring.aspect.Loggable)")
public void myAdvice(){
System.out.println("Executing myAdvice!!");
}
}
Die myAdvice() Methode wird nur die setName() Methode beraten. Dies ist ein sehr sicherer Ansatz und wann immer wir den Ratschlag auf eine Methode anwenden möchten, müssen wir sie einfach mit der Loggable-Annotation kennzeichnen.
Spring AOP XML-Konfiguration
I always prefer annotation but we also have the option to configure aspects in the spring configuration file. For example, let’s say we have a class as below. EmployeeXMLConfigAspect.java code:
package com.journaldev.spring.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
public class EmployeeXMLConfigAspect {
public Object employeeAroundAdvice(ProceedingJoinPoint proceedingJoinPoint){
System.out.println("EmployeeXMLConfigAspect:: Before invoking getName() method");
Object value = null;
try {
value = proceedingJoinPoint.proceed();
} catch (Throwable e) {
e.printStackTrace();
}
System.out.println("EmployeeXMLConfigAspect:: After invoking getName() method. Return value="+value);
return value;
}
}
Wir können dies konfigurieren, indem wir die folgende Konfiguration in die Spring Bean-Konfigurationsdatei aufnehmen.
<bean name="employeeXMLConfigAspect" class="com.journaldev.spring.aspect.EmployeeXMLConfigAspect" />
<!-- Spring AOP XML Configuration -->
<aop:config>
<aop:aspect ref="employeeXMLConfigAspect" id="employeeXMLConfigAspectID" order="1">
<aop:pointcut expression="execution(* com.journaldev.spring.model.Employee.getName())" id="getNamePointcut"/>
<aop:around method="employeeAroundAdvice" pointcut-ref="getNamePointcut" arg-names="proceedingJoinPoint"/>
</aop:aspect>
</aop:config>
Die Zwecke der AOP-XML-Konfigurationselemente sind aus ihren Namen klar ersichtlich, daher gehe ich nicht weiter darauf ein.
Beispiel für Spring AOP
Lassen Sie uns ein einfaches Spring-Programm erstellen und sehen, wie all diese Aspekte sich durch die Bean-Methoden durchschneiden. SpringMain.java-Code:
package com.journaldev.spring.main;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.journaldev.spring.service.EmployeeService;
public class SpringMain {
public static void main(String[] args) {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml");
EmployeeService employeeService = ctx.getBean("employeeService", EmployeeService.class);
System.out.println(employeeService.getEmployee().getName());
employeeService.getEmployee().setName("Pankaj");
employeeService.getEmployee().throwException();
ctx.close();
}
}
Wenn wir das obige Programm ausführen, erhalten wir die folgende Ausgabe.
Mar 20, 2014 8:50:09 PM org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@4b9af9a9: startup date [Thu Mar 20 20:50:09 PDT 2014]; root of context hierarchy
Mar 20, 2014 8:50:09 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [spring.xml]
Service method getter called
Before executing service method
EmployeeXMLConfigAspect:: Before invoking getName() method
Executing Advice on getName()
Executing loggingAdvice on getName()
Executing secondAdvice on getName()
Before invoking getName() method
After invoking getName() method. Return value=Dummy Name
getNameReturningAdvice executed. Returned String=Dummy Name
EmployeeXMLConfigAspect:: After invoking getName() method. Return value=Dummy Name
Dummy Name
Service method getter called
Before executing service method
String argument passed=Pankaj
Before running loggingAdvice on method=execution(void com.journaldev.spring.model.Employee.setName(String))
Agruments Passed=[Pankaj]
Executing myAdvice!!
Running After Advice. String argument passed=Pankaj
Service method getter called
Before executing service method
Exception thrown in Employee Method=execution(void com.journaldev.spring.model.Employee.throwException())
Exception in thread "main" java.lang.RuntimeException: Dummy Exception
at com.journaldev.spring.model.Employee.throwException(Employee.java:19)
at com.journaldev.spring.model.Employee$$FastClassBySpringCGLIB$$da2dc051.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:711)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:58)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:644)
at com.journaldev.spring.model.Employee$$EnhancerBySpringCGLIB$$3f881964.throwException(<generated>)
at com.journaldev.spring.main.SpringMain.main(SpringMain.java:17)
Sie können sehen, dass die Ratschläge basierend auf ihren Pointcut-Konfigurationen nacheinander ausgeführt werden. Sie sollten sie einzeln konfigurieren, um Verwirrung zu vermeiden. Das ist alles für Spring-AOP-Beispiel-Tutorial, ich hoffe, Sie haben die Grundlagen von AOP mit Spring gelernt und können mehr aus Beispielen lernen. Laden Sie das Beispielprojekt über den untenstehenden Link herunter und spielen Sie damit herum.