Spring Framework is ontwikkeld op twee kernconcepten – Dependency Injection en Aspect Oriented Programming (Spring AOP).
Spring AOP
We hebben al gezien hoe Spring Dependency Injection werkt, vandaag zullen we ingaan op de kernconcepten van Aspect-Oriented Programming en hoe we het kunnen implementeren met behulp van Spring Framework.
Spring AOP Overzicht
De meeste bedrijfstoepassingen hebben enkele gemeenschappelijke dwarsdoorsnijdende zorgen die van toepassing zijn op verschillende soorten objecten en modules. Enkele van de veelvoorkomende dwarsdoorsnijdende zorgen zijn logging, transactiebeheer, gegevensvalidatie, enzovoort. In Objectgeoriënteerd programmeren wordt modulariteit van de toepassing bereikt door middel van klassen, terwijl in Aspectgeoriënteerd programmeren modulariteit wordt bereikt door aspecten, die geconfigureerd zijn om dwars door verschillende klassen heen te snijden. Spring AOP verwijdert de directe afhankelijkheid van dwarsdoorsnijdende taken van klassen die we niet kunnen bereiken via het normale objectgeoriënteerde programmeermodel. Bijvoorbeeld, we kunnen een aparte klasse hebben voor logging, maar de functionele klassen moeten toch deze methoden aanroepen om logging in de hele toepassing te bereiken.
Core Concepts van Aspectgeoriënteerd programmeren
Voordat we in de implementatie van Spring AOP duiken, moeten we de kernconcepten van AOP begrijpen.
- Aspect: Een aspect is een klasse die concerns van de bedrijfstoepassing implementeert die dwars door meerdere klassen heen snijden, zoals transactiebeheer. Aspecten kunnen een normale klasse zijn geconfigureerd via Spring XML-configuratie of we kunnen Spring AspectJ-integratie gebruiken om een klasse als aspect te definiëren met behulp van de
@Aspect
-annotatie. - Join Point: Een join point is een specifiek punt in de applicatie zoals method uitvoering, uitzonderingsafhandeling, veranderende objectvariabele waarden, enz. In Spring AOP is een join point altijd de uitvoering van een methode.
- Advies: Adviezen zijn acties die worden ondernomen voor een bepaald join point. In termen van programmeren zijn het methoden die worden uitgevoerd wanneer een bepaald join point met overeenkomende pointcut wordt bereikt in de applicatie. Je kunt Adviezen zien als Struts2-interceptors of Servlet Filters.
- Pointcut: Pointcut is expressies die overeenkomen met join points om te bepalen of advies moet worden uitgevoerd of niet. Pointcut gebruikt verschillende soorten expressies die overeenkomen met de join points en het Spring-framework gebruikt de AspectJ-pointcut-expressietaal.
- Doelobject: Dit zijn de objecten waarop adviezen worden toegepast. Spring AOP wordt geïmplementeerd met behulp van runtime-proxies, dus dit object is altijd een geproxificeerd object. Wat dit betekent is dat er op runtime een subklasse wordt gemaakt waar de doelmethode wordt overschreven en adviezen worden toegevoegd op basis van hun configuratie.
- AOP-proxy: De implementatie van Spring AOP gebruikt JDK-dynamische proxy om de proxyklassen te maken met doelklassen en adviesoproepen; deze worden AOP-proxyklassen genoemd. We kunnen ook CGLIB-proxy gebruiken door het als afhankelijkheid toe te voegen in het Spring AOP-project.
- Weven: Dit is het proces van het koppelen van aspecten aan andere objecten om de geadviseerde proxy-objecten te maken. Dit kan worden gedaan tijdens het compileren, laden of tijdens runtime. Spring AOP voert het weven uit tijdens runtime.
AOP Advies Types
Op basis van de uitvoeringsstrategie van advies zijn ze van de volgende typen.
- Voor Advies: Deze adviezen worden uitgevoerd vóór de uitvoering van join point-methoden. We kunnen de
@Before
-annotatie gebruiken om een adviestype als Voor advies te markeren. - Na (eindelijk) Advies: Een advies dat wordt uitgevoerd nadat de join point-methode klaar is met uitvoeren, normaal of door een uitzondering te gooien. We kunnen after-advies maken met behulp van de
@After
-annotatie. - Na Terugkerend Advies: Soms willen we dat adviesmethoden alleen worden uitgevoerd als de join point-methode normaal wordt uitgevoerd. We kunnen de
@AfterReturning
-annotatie gebruiken om een methode als na terugkerend advies te markeren. - Na het geven van advies: Dit advies wordt alleen uitgevoerd wanneer het join-puntmethode een uitzondering genereert, we kunnen het gebruiken om de transactie declaratief terug te draaien. We gebruiken de
@AfterThrowing
-annotatie voor dit type advies. - Omringend advies: Dit is het belangrijkste en krachtigste advies. Dit advies omringt de join-puntmethode en we kunnen ook kiezen of we de join-puntmethode uitvoeren of niet. We kunnen adviescode schrijven die wordt uitgevoerd vóór en na de uitvoering van de join-puntmethode. Het is de verantwoordelijkheid van omringend advies om de join-puntmethode aan te roepen en waarden terug te geven als de methode iets retourneert. We gebruiken de
@Around
-annotatie om omringend adviesmethoden te maken.
De hierboven genoemde punten klinken misschien verwarrend, maar wanneer we naar de implementatie van Spring AOP kijken, zullen de zaken duidelijker worden. Laten we een eenvoudig Spring-project met AOP-implementaties gaan maken. Spring biedt ondersteuning voor het gebruik van AspectJ-annotaties om aspecten te creëren en we zullen dat voor eenvoud gebruiken. Alle bovenstaande AOP-annotaties zijn gedefinieerd in het pakket org.aspectj.lang.annotation
. Spring Tool Suite biedt nuttige informatie over de aspecten, dus ik zou je aanraden om het te gebruiken. Als je niet bekend bent met STS, zou ik je aanraden om een kijkje te nemen bij Spring MVC Tutorial waarin ik uitleg hoe je het moet gebruiken.
Spring AOP Voorbeeld
Maak een nieuw eenvoudig Spring Maven-project aan zodat alle Spring Core-bibliotheken zijn opgenomen in de pom.xml-bestanden en we ze niet expliciet hoeven toe te voegen. Ons uiteindelijke project zal eruit zien als de onderstaande afbeelding, we zullen de Spring Core-componenten en Aspect-implementaties gedetailleerd bekijken.
Spring AOP AspectJ afhankelijkheden
Het Spring-framework biedt standaard AOP-ondersteuning, maar omdat we AspectJ-annotaties gebruiken voor het configureren van aspecten en advies, moeten we deze toevoegen aan het pom.xml-bestand.
<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>
Merk op dat ik aspectjrt
en aspectjtools
afhankelijkheden (versie 1.7.4) aan het project heb toegevoegd. Ook heb ik de Spring-frameworkversie bijgewerkt naar de nieuwste versie van dit moment, namelijk 4.0.2.RELEASE.
Modelklasse
Laten we een eenvoudige Java Bean maken die we zullen gebruiken voor ons voorbeeld met enkele extra methoden. Code van Employee.java:
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");
}
}
Heb je gemerkt dat de methode setName()
is geannoteerd met de Loggable
-annotatie? Het is een custom Java-annotatie die door ons is gedefinieerd in het project. We zullen later naar het gebruik ervan kijken.
Serviceklasse
Laten we een serviceklasse maken om met het werknemerobject te werken. De code van EmployeeService.java ziet er als volgt uit:
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-configuratie met AOP
Als je STS gebruikt, heb je de optie om een “Spring Bean Configuration File” te maken en het AOP-schema namespace te kiezen, maar als je een andere IDE gebruikt, kun je het eenvoudig toevoegen in het configuratiebestand van de spring bean. Mijn project configuratiebestand ziet er als volgt uit: 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>
Om Spring AOP te gebruiken in Spring beans, moeten we het volgende doen:
- Declareer de AOP-namespace zoals xmlns:aop=“https://www.springframework.org/schema/aop”
- Voeg het aop:aspectj-autoproxy-element toe om Spring AspectJ-ondersteuning in te schakelen met automatische proxy tijdens runtime
- Configureer Aspect-klassen als andere Spring beans
Je kunt zien dat ik veel aspecten heb gedefinieerd in het configuratiebestand van de Spring-bean. Het is tijd om ze één voor één te bekijken.
Voorbeeld van Spring AOP Before Aspect
Code van EmployeeAspect.java:
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");
}
}
Belangrijke punten in de bovenstaande aspectklasse zijn:
- Aspect-klassen moeten de annotatie
@Aspect
hebben. - @Before-annotatie wordt gebruikt om Before-advies te creëren.
- De tekenreeksparameter doorgegeven in de annotatie
@Before
is de Pointcut-uitdrukking. - Advies getNameAdvice() wordt uitgevoerd voor elke methode van de Spring Bean met de signatuur
public String getName()
. Dit is een zeer belangrijk punt om te onthouden; als we een Employee-bean maken met de new-operator, worden de adviezen niet toegepast. Alleen als we ApplicationContext gebruiken om de bean te krijgen, worden de adviezen toegepast. - We kunnen een asterisk (*) gebruiken als wildcard in Pointcut-uitdrukkingen, getAllAdvice() wordt toegepast op alle klassen in het pakket
com.journaldev.spring.service
waarvan de naam begint metget
en geen argumenten heeft.
We zullen naar het advies in actie kijken in een testklasse nadat we alle verschillende soorten adviezen hebben besproken.
Spring AOP Pointcut Methoden en Hergebruik
Soms moeten we dezelfde Pointcut-uitdrukking op meerdere plaatsen gebruiken. We kunnen een lege methode maken met de annotatie @Pointcut
en deze vervolgens gebruiken als een expressie in de adviezen. Code van EmployeeAspectPointcut.java:
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 om uit te voeren op alle methoden van klassen in een pakket
@Pointcut("within(com.journaldev.spring.service.*)")
public void allMethodsPointcut(){}
}
Het bovenstaande voorbeeld is zeer duidelijk, in plaats van een expressie gebruiken we de methode naam in het adviesannotatie-argument.
Spring AOP JoinPoint en Adviesargumenten
We kunnen JoinPoint als een parameter gebruiken in de adviesmethoden en hiermee de methodehandtekening of het doelobject verkrijgen. We kunnen de args()
-expressie in de pointcut gebruiken die moet worden toegepast op elke methode die overeenkomt met het argumentpatroon. Als we dit gebruiken, moeten we dezelfde naam in de adviesmethode gebruiken waar het argumenttype wordt bepaald. We kunnen ook generieke objecten gebruiken in de adviesargumenten. Code van EmployeeAspectJoinPoint.java:
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()));
}
//Adviesargumenten, worden toegepast op bean-methoden met één String-argument
@Before("args(name)")
public void logStringArguments(String name){
System.out.println("String argument passed="+name);
}
}
Voorbeeld van Spring AOP na-advies
Laten we eens kijken naar een eenvoudige aspectklasse met een voorbeeld van After, After Throwing en After Returning advies. Code van EmployeeAfterAspect.java:
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);
}
}
We kunnen within
gebruiken in het pointcut-expressie om het advies toe te passen op alle methoden in de klasse. We kunnen het advies @AfterReturning gebruiken om het object te krijgen dat geretourneerd wordt door de geadviseerde methode. We hebben de methode throwException() in de Employee bean om het gebruik van After Throwing advies te demonstreren.
Voorbeeld van Spring AOP Around Aspect
Zoals eerder uitgelegd, kunnen we Around aspect gebruiken om de method uitvoering te knippen voor en na. We kunnen het gebruiken om te controleren of de geadviseerde methode al dan niet zal worden uitgevoerd. We kunnen ook de geretourneerde waarde inspecteren en wijzigen. Dit is het krachtigste advies en moet correct worden toegepast. Code van EmployeeAroundAspect.java:
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;
}
}
Rond advies is altijd vereist om ProceedingJoinPoint als een argument te hebben en we moeten de proceed() methode ervan gebruiken om de methode van het doelobject te adviseren. Als de geadviseerde methode iets retourneert, is het de verantwoordelijkheid van het advies om het aan de aanroepende programma terug te geven. Voor void-methoden kan de adviesmethode null retourneren. Aangezien rond advies rond de geadviseerde methode snijdt, kunnen we ook de invoer en uitvoer van de methode controleren, evenals het uitvoeringsgedrag ervan.
Spring Advies met Aangepast Annotation Pointcut
Als je kijkt naar alle bovenstaande adviespuntuitdrukkingen, bestaat de kans dat ze worden toegepast op andere beans waar het niet bedoeld is. Bijvoorbeeld, iemand kan een nieuwe Spring bean definiëren met een getName() methode en het advies zal beginnen toegepast te worden, zelfs als dat niet de bedoeling was. Daarom moeten we de reikwijdte van de puntuitdrukking zo smal mogelijk houden. Een alternatieve aanpak is het creëren van een aangepaste annotatie en de methoden annoteren waar we willen dat het advies wordt toegepast. Dit is het doel van het hebben van de Employee setName() methode geannoteerd met de @Loggable annotatie. De Spring Framework @Transactional annotatie is een geweldig voorbeeld van deze aanpak voor Spring Transaction Management. 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!!");
}
}
De myAdvice() methode zal alleen advies geven aan de setName() methode. Dit is een zeer veilige aanpak en wanneer we het advies op een bepaalde methode willen toepassen, hoeven we deze alleen maar te annoteren met de Loggable annotatie.
Spring AOP XML-configuratie
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;
}
}
We kunnen het configureren door de volgende configuratie op te nemen in het Spring Bean-configuratiebestand.
<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>
AOP xml-configuratie-elementen hebben hun doel duidelijk in hun naam, dus ik zal er niet te veel in detail over gaan.
Voorbeeld van Spring AOP
Laten we een eenvoudig Spring-programma bekijken en zien hoe al deze aspecten door de bean-methoden snijden. Code van SpringMain.java:
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();
}
}
Wanneer we het bovenstaande programma uitvoeren, krijgen we de volgende uitvoer.
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)
Je kunt zien dat adviezen één voor één worden uitgevoerd op basis van hun pointcut-configuraties. Je moet ze één voor één configureren om verwarring te voorkomen. Dat is alles voor Spring AOP Voorbeeld Zelfstudie. Ik hoop dat je de basisprincipes van AOP met Spring hebt geleerd en meer kunt leren aan de hand van voorbeelden. Download het voorbeeldproject vanaf de onderstaande link en experimenteer ermee.