KEMBAR78
10 Spring Boot 3 Aop | PDF | Spring Framework | Computer Science
0% found this document useful (0 votes)
206 views198 pages

10 Spring Boot 3 Aop

This document provides an overview of aspect-oriented programming (AOP) and how it can be used to address issues like code tangling and scattering that arise when adding cross-cutting concerns like logging and security to an application. It describes how AOP works by encapsulating cross-cutting logic into reusable aspects that can be configured to advise target objects. The key benefits of AOP are that it keeps business logic clean and aspects can be applied and changed selectively without touching the main application code. It also discusses some common AOP use cases and frameworks like Spring AOP and AspectJ.

Uploaded by

def46917
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
206 views198 pages

10 Spring Boot 3 Aop

This document provides an overview of aspect-oriented programming (AOP) and how it can be used to address issues like code tangling and scattering that arise when adding cross-cutting concerns like logging and security to an application. It describes how AOP works by encapsulating cross-cutting logic into reusable aspects that can be configured to advise target objects. The key benefits of AOP are that it keeps business logic clean and aspects can be applied and changed selectively without touching the main application code. It also discusses some common AOP use cases and frameworks like Spring AOP and AspectJ.

Uploaded by

def46917
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 198

Aspect-Oriented Programming (AOP)

Overview

© luv2code LLC
Application Architecture

Account Account Account


Controller Service DAO

www.luv2code.com © luv2code LLC


Code for Data Access Object (DAO)

public void addAccount(Account theAccount, String userId) {

entityManager.persist(theAccount);
}

www.luv2code.com © luv2code LLC


New Requirement - Logging From: The B
oss
• Need to add logging to our DAO methods

• Add some logging statements before the start of the method

• Possibly more places … but get started on that ASAP!

www.luv2code.com © luv2code LLC


DAO - Add Logging Code

public void addAccount(Account theAccount, String userId) {

entityManager.persist(theAccount);

www.luv2code.com © luv2code LLC


DAO - Add Logging Code

public void addAccount(Account theAccount, String userId) {

entityManager.persist(theAccount);

www.luv2code.com © luv2code LLC


New Requirement - Security From: The B
oss
• Need to add security code to our DAO

• Make sure user is authorized before running DAO method

www.luv2code.com © luv2code LLC


Add Security Code

public void addAccount(Account theAccount, String userId) {

entityManager.persist(theAccount);

www.luv2code.com © luv2code LLC


Add Security Code

public void addAccount(Account theAccount, String userId) {

entityManager.persist(theAccount);

www.luv2code.com © luv2code LLC


Add Security Code

public void addAccount(Account theAccount, String userId) {

entityManager.persist(theAccount);

www.luv2code.com © luv2code LLC


By the way From: The B
oss
• Let’s add it to all of our layers…

Account Account Account


Controller Service DAO

www.luv2code.com © luv2code LLC


I'm Going Crazy Over Here

www.luv2code.com © luv2code LLC


Two Main Problems
• Code Tangling

• For a given method: addAccount(…)

• We have logging and security code tangled in

• Code Scattering

• If we need to change logging or security code

• We have to update ALL classes

www.luv2code.com © luv2code LLC


Other possible solutions?
• Inheritance?

• Every class would need to inherit from a base class

• Can all classes extends from your base class? … plus no multiple inheritance

• Delegation?

• Classes would delegate logging, security calls

• Still would need to update classes if we wanted to

• add/remove logging or security

• add new feature like auditing, API management, instrumentation

www.luv2code.com © luv2code LLC


Aspect-Oriented Programming
• Programming technique based on concept of an Aspect

• Aspect encapsulates cross-cutting logic

Cross-Cutting Concerns

• “Concern” means logic / functionality

www.luv2code.com © luv2code LLC


Cross-Cutting Concerns

Account Account Account


Controller Service DAO

S S S
L L L
E E E
O Product O Product O Product
C C C
G Controller G Service G DAO
U U U
G G G
R R R
I I I
I I I
N N N
T T T
G Blog G Blog G Blog
Y Y Y
Controller Service DAO

www.luv2code.com © luv2code LLC


Aspects
• Aspect can be reused at multiple locations

• Same aspect/class … applied based on con guration

fi
Account Account Account
Controller Service DAO

www.luv2code.com © luv2code LLC


AOP Solution
• Apply the Proxy design pattern

Main AOP Logging Security Target


App Proxy Aspect Aspect Object

MainApp TargetObject

// call target object public void doSomeStuff() {


targetObj.doSomeStuff(); …
}

www.luv2code.com © luv2code LLC


Benefits of AOP
• Code for Aspect is de ned in a single class

fi
• Much better than being scattered everywhere

• Promotes code reuse and easier to change

• Business code in your application is cleaner

• Only applies to business functionality: addAccount

• Reduces code complexity

• Con gurable
fi
• Based on con guration, apply Aspects selectively to different parts of app
fi
• No need to make changes to main application code … very important!

www.luv2code.com © luv2code LLC


Additional AOP Use Cases
• Most common

• logging, security, transactions

• Audit logging

• who, what, when, where

• Exception handling

• log exception and notify DevOps team via SMS/email

• API Management

• how many times has a method been called user

• analytics: what are peak times? what is average load? who is top user?

www.luv2code.com © luv2code LLC


AOP: Advantages and Disadvantages
Advantages Disadvantages
• Reusable modules
• Too many aspects and
• Resolve code tangling app ow is hard to

fl
follow
• Resolve code scatter
• Minor performance
• Applied selectively based cost for aspect
on con guration execution
fi
(run-time weaving)

www.luv2code.com © luv2code LLC


Aspect-Oriented Programming (AOP)
Spring AOP Support

© luv2code LLC
AOP Terminology
• Aspect: module of code for a cross-cutting concern (logging, security, …)

• Advice: What action is taken and when it should be applied

• Join Point: When to apply code during program execution

• Pointcut: A predicate expression for where advice should be applied

www.luv2code.com © luv2code LLC


Advice Types
• Before advice: run before the method

• After nally advice: run after the method ( nally)


fi
fi
• After returning advice: run after the method (success execution)

• After throwing advice: run after method (if exception thrown)

• Around advice: run before and after method

www.luv2code.com © luv2code LLC


Weaving
• Connecting aspects to target objects to create an advised object

• Different types of weaving

• Compile-time, load-time or run-time

• Regarding performance: run-time weaving is the slowest

www.luv2code.com © luv2code LLC


AOP Frameworks
• Two leading AOP Frameworks for Java

Spring AOP AspectJ

www.luv2code.com © luv2code LLC


Spring AOP Support
• Spring provides AOP support

• Key component of Spring

• Security, transactions, caching etc

• Uses run-time weaving of aspects

www.luv2code.com © luv2code LLC


AspectJ
• Original AOP framework, released in 2001

• www.eclipse.org/aspectj

• Provides complete support for AOP

• Rich support for

• join points: method-level, constructor, eld

fi
• code weaving: compile-time, post compile-time and load-time

www.luv2code.com © luv2code LLC


Spring AOP Comparison
Advantages Disadvantages
• Simpler to use than AspectJ • Only supports method-level
join points
• Uses Proxy pattern
• Can only apply aspects to beans created
• Can migrate to AspectJ when using by Spring app context
@Aspect annotation
• Minor performance cost for aspect
execution
(run-time weaving)

www.luv2code.com © luv2code LLC


AspectJ Comparison
Advantages Disadvantages
• Support all join points • Compile-time weaving
requires extra compilation
• Works with any POJO, not just
step
beans from app context
• AspectJ pointcut syntax can
• Faster performance compared
become complex
to Spring AOP

• Complete AOP support

www.luv2code.com © luv2code LLC


Comparing Spring AOP and AspectJ
• Spring AOP only supports

• Method-level join points

• Run-time code weaving (slower than AspectJ)

• AspectJ supports

• join points: method-level, constructor, eld

fi
• weaving: compile-time, post compile-time and load-time

www.luv2code.com © luv2code LLC


Comparing Spring AOP and AspectJ
• Spring AOP is a light implementation of AOP

• Solves common problems in enterprise applications

• My recommendation

• Start with Spring AOP … easy to get started with

• If you have complex requirements then move to AspectJ

www.luv2code.com © luv2code LLC


Additional Resources
• Spring Reference Manual: www.spring.io

• AspectJ in Action

• by Raminvas Laddad

• Aspect-Oriented Development with Use Cases

• by Ivar Jacobson and Pan-Wei Ng

www.luv2code.com © luv2code LLC


Aspect-Oriented Programming (AOP)
@Before Advice
Advice Types

• Before advice: run before the method

• After returning advice: run after the method (success execution)

• After throwing advice: run after method (if exception thrown)

• After nally advice: run after the method ( nally)


fi
fi
• Around advice: run before and after method

www.luv2code.com
@Before Advice - Interaction

Main AOP Logging Security Target


App Proxy Aspect Aspect Object

MainApp TargetObject

// call target object public void doSomeStuff() {


targetObj.doSomeStuff(); …
}

www.luv2code.com
Advice - Interaction

@Before

www.luv2code.com
Advice - Interaction

@Before

@AfterReturning

www.luv2code.com
@Before Advice - Use Cases
• Most common

• logging, security, transactions

• Audit logging

• who, what, when, where

• API Management

• how many times has a method been called user

• analytics: what are peak times? what is average load? who is top user?

www.luv2code.com
AOP Example - Overview Step-
By-S
tep

Target
Main AOP Logging Object
App Proxy Aspect
AccountDAO

MainApp TargetObject - AccountDAO

// call target object public void addAccount() {


theAccountDAO.addAccount(); …
}

www.luv2code.com
Spring Boot AOP Starter
• Add the dependency for Spring Boot AOP Starter

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>

• Since this dependency is part of our pom.xml

• Spring Boot will automatically enable support for AOP

• No need to explicitly use @EnableAspectJAutoProxy … we get it for free

www.luv2code.com
Development Process - @Before Step-
By-S
tep

1. Create target object: AccountDAO

2. Create main app

3. Create an Aspect with @Before advice

www.luv2code.com
Step 1: Create Target Object: AccountDAO
public interface AccountDAO {

void addAccount() {
}

@Component
public class AccountDAOImpl implements AccountDAO {

public void addAccount() {

System.out.println("DOING MY DB WORK: ADDING AN ACCOUNT");

}
}

www.luv2code.com
Step 2: Create main app
@SpringBootApplication
public class AopdemoApplication {

public static void main(String[] args) {


SpringApplication.run(AopdemoApplication.class, args);
}

@Bean
public CommandLineRunner commandLineRunner(AccountDAO theAccountDAO) {

return runner -> {

demoTheBeforeAdvice(theAccountDAO);
};
}

private void demoTheBeforeAdvice(AccountDAO theAccountDAO) {

// call the business method


theAccountDAO.addAccount();
}

www.luv2code.com
Step 3: Create an Aspect with @Before advice

@Aspect
@Component
public class MyDemoLoggingAspect {

...

www.luv2code.com
Step 3: Create an Aspect with @Before advice

@Aspect
@Component
public class MyDemoLoggingAspect {

@Before("execution(public void addAccount())")


public void beforeAddAccountAdvice() {

...

www.luv2code.com
Step 3: Create an Aspect with @Before advice

@Aspect
@Component
public class MyDemoLoggingAspect {

@Before("execution(public void addAccount())")


public void beforeAddAccountAdvice() {

System.out.println("Executing @Before advice on addAccount()");

www.luv2code.com
Best Practices: Aspect and Advices

• Keep the code small

• Keep the code fast

• Do not perform any expensive / slow operations

• Get in and out as QUICKLY as possible

www.luv2code.com
AOP - Pointcut Expressions
I made a promise to you …

www.luv2code.com
AOP Terminology

• Pointcut: A predicate expression for where advice should be applied

www.luv2code.com
Pointcut Expression Language
• Spring AOP uses AspectJ’s pointcut expression language

• We will start with execution pointcuts

• Applies to execution of methods

www.luv2code.com
Match on Method Name

www.luv2code.com
Pointcut Expression Language

execution(modi ers-pattern? return-type-pattern declaring-type-pattern?


fi
method-name-pattern(param-pattern) throws-pattern?)

• The pattern is optional if it has “?”

www.luv2code.com
Pointcut Expression Examples
Match on method names

• Match only addAccount() method in AccountDAO class

Return
Modifier type

@Before("execution(public void com.luv2code.aopdemo.dao.AccountDAO.addAccount())")

Declaring Method

www.luv2code.com
Pointcut Expression Examples
Match on method names

• Match any addAccount() method in any class

Return
Modifier
type

@Before("execution(public void addAccount())")

Method

www.luv2code.com
Pointcut Expression Examples
Match on method names (using wildcards)

• Match methods starting with add in any class

Return
Modifier type

@Before("execution(public void add*())”)

Method

www.luv2code.com
Pointcut Expression Examples
Match on method names (using wildcards)

• Match methods starting with processCreditCard in any class

Return
Modifier type

@Before("execution(public Veri cationResult processCreditCard*())”)

fi
Method

www.luv2code.com
Pointcut Expression Examples
• Use wildcards on return type

Return
type

@Before(“execution(public * processCreditCard*())”)

Method

www.luv2code.com
Pointcut Expression Examples
• Modi er is optional … so you don’t have to list it
fi
Return
type

@Before(“execution(* processCreditCard*())”)

Method

www.luv2code.com
AOP - Pointcut Expressions (cont)
Match on Parameters

www.luv2code.com
Parameter Pattern Wildcards

• For param-pattern

• () - matches a method with no arguments

• (*) - matches a method with one argument of any type

• (..) - matches a method with 0 or more arguments of any type

www.luv2code.com
Pointcut Expression Examples
Match on method parameters

• Match addAccount methods with no arguments

www.luv2code.com
Pointcut Expression Examples
Match on method parameters

• Match addAccount methods with no arguments

Return Param
type no-args

@Before("execution(* addAccount())")

Method

www.luv2code.com
Pointcut Expression Examples
Match on method parameters

• Match addAccount methods that have Account param


Param
Return Type
type

@Before("execution(* addAccount(com.luv2code.aopdemo.Account))")

Method

www.luv2code.com
Pointcut Expression Examples
Match on method parameters (using wildcards)

• Match addAccount methods with any number of arguments

www.luv2code.com
Pointcut Expression Examples
Match on method parameters (using wildcards)

• Match addAccount methods with any number of arguments

Return Param
type Type

@Before("execution(* addAccount(..))”)

Method

www.luv2code.com
Match on Package

www.luv2code.com
Package - Pointcut Expression Examples
Match on methods in a package

• Match any method in our DAO package: com.luv2code.aopdemo.dao


Return Package Param
type Type

@Before("execution(* com.luv2code.aopdemo.dao.*.*(..))")

Class Method

www.luv2code.com
If you are using IntelliJ Ultimate
You may encounter this error
Exception encountered during context initialization - cancelling
refresh attempt:
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'mbeanExporter' defined in class path
resource [org/springframework/boot/autoconfigure/jmx/
JmxAutoConfiguration.class]

© luv2code LLC
Why?

IntelliJ Ultimate loads additional classes for JMX

This conflicts with Spring Boot’s JMX Autoconfiguration

© luv2code LLC
When using wildcards with AOP,
caution should be taken.

If new frameworks are added to your project,


then you may encounter conflicts.

Recommendation is to:
- narrow your pointcut expressions
- limit them to your project package

© luv2code LLC
In this case, our pointcut expression is too broad.

We can resolve this by:


- narrowing the pointcut expression
- only match within our project package

@Before("execution(* com.luv2code..add*(..))")

Narrow pointcut expression to our package

© luv2code LLC
Aspect-Oriented Programming (AOP)
Pointcut Declarations
Problem
• How can we reuse a pointcut expression?

• Want to apply to multiple advices

@Before("execution(* com.luv2code.aopdemo.dao.*.*(..))")
public void beforeAddAccountAdvice() {
...
}

www.luv2code.com
Possible Solution
• Could just do the old copy/paste method … yuk!

@Before("execution(* com.luv2code.aopdemo.dao.*.*(..))")
public void beforeAddAccountAdvice() {
...
}

www.luv2code.com
Possible Solution
• Could just do the old copy/paste method … yuk!

@Before("execution(* com.luv2code.aopdemo.dao.*.*(..))")
public void beforeAddAccountAdvice() {
...
}

@Before("execution(* com.luv2code.aopdemo.dao.*.*(..))")
public void performApiAnalytics() {
...
}

www.luv2code.com
Ideal Solution

• Create a pointcut declaration once

• Apply it to multiple advices

www.luv2code.com
Development Process Step-
By-S
tep

1. Create a pointcut declaration

2. Apply pointcut declaration to advice(s)

www.luv2code.com
Step 1- Create Pointcut Declaration
• Create a pointcut declaration once

@Pointcut("execution(* com.luv2code.aopdemo.dao.*.*(..))")
private void forDaoPackage() {}

www.luv2code.com
Step 1- Create Pointcut Declaration
@Aspect
@Component
public class MyDemoLoggingAspect {

www.luv2code.com
Step 1- Create Pointcut Declaration
@Aspect
@Component
public class MyDemoLoggingAspect {

@Pointcut("execution(* com.luv2code.aopdemo.dao.*.*(..))")
private void forDaoPackage() {}

www.luv2code.com
Step 2 - Apply to Multiple Advices
@Aspect
@Component
public class MyDemoLoggingAspect {

@Pointcut("execution(* com.luv2code.aopdemo.dao.*.*(..))")
private void forDaoPackage() {}

@Before("forDaoPackage()")
public void beforeAddAccountAdvice() {

}

www.luv2code.com
Step 2 - Apply to Multiple Advices
@Aspect
@Component
public class MyDemoLoggingAspect {

@Pointcut("execution(* com.luv2code.aopdemo.dao.*.*(..))")
private void forDaoPackage() {}

@Before("forDaoPackage()")
public void beforeAddAccountAdvice() {

}

@Before("forDaoPackage()")
public void performApiAnalytics() {

}

www.luv2code.com
Benefits of Pointcut Declarations

• Easily reuse pointcut expressions

• Update pointcut in one location

• Can also share and combine pointcut expressions (coming up later)

www.luv2code.com
Aspect-Oriented Programming (AOP)
Combine Pointcuts
Problem
• How to apply multiple pointcut expressions to single advice?

• Execute an advice only if certain conditions are met

• For example

• All methods in a package EXCEPT getter/setter methods

www.luv2code.com
Combining Pointcut Expressions
• Combine pointcut expressions using logic operators

• AND (&&)

• OR (||)

• NOT (!)

www.luv2code.com
Combining Pointcut Expressions
• Works like an “if” statement

• Execution happens only if it evaluates to true

@Before(“expressionOne() && expressionTwo()”)

@Before(“expressionOne() || expressionTwo()”)

@Before(“expressionOne() && !expressionTwo()”)

www.luv2code.com
Example:
• All methods in a package EXCEPT getter/setter methods

www.luv2code.com
Development Process Step-
By-S
tep

1. Create a pointcut declarations

2. Combine pointcut declarations

3. Apply pointcut declaration to advice(s)

www.luv2code.com
Step 1- Create Pointcut Declaration

@Pointcut("execution(* com.luv2code.aopdemo.dao.*.*(..))")
private void forDaoPackage() {}

// create pointcut for getter methods


@Pointcut("execution(* com.luv2code.aopdemo.dao.*.get*(..))")
private void getter() {}

// create pointcut for setter methods


@Pointcut("execution(* com.luv2code.aopdemo.dao.*.set*(..))")
private void setter() {}

www.luv2code.com
Step 1- Create Pointcut Declaration

@Pointcut("execution(* com.luv2code.aopdemo.dao.*.*(..))")
private void forDaoPackage() {}

// create pointcut for getter methods


@Pointcut("execution(* com.luv2code.aopdemo.dao.*.get*(..))")
private void getter() {}

// create pointcut for setter methods


@Pointcut("execution(* com.luv2code.aopdemo.dao.*.set*(..))")
private void setter() {}

www.luv2code.com
Step 1- Create Pointcut Declaration

@Pointcut("execution(* com.luv2code.aopdemo.dao.*.*(..))")
private void forDaoPackage() {}

// create pointcut for getter methods


@Pointcut("execution(* com.luv2code.aopdemo.dao.*.get*(..))")
private void getter() {}

// create pointcut for setter methods


@Pointcut("execution(* com.luv2code.aopdemo.dao.*.set*(..))")
private void setter() {}

www.luv2code.com
Step 2 - Combine Pointcut Declarations
@Pointcut("execution(* com.luv2code.aopdemo.dao.*.*(..))")
private void forDaoPackage() {}

// create pointcut for getter methods


@Pointcut("execution(* com.luv2code.aopdemo.dao.*.get*(..))")
private void getter() {}

// create pointcut for setter methods


@Pointcut("execution(* com.luv2code.aopdemo.dao.*.set*(..))")
private void setter() {}

// combine pointcut: include package ... exclude getter/setter


@Pointcut("forDaoPackage() && !(getter() || setter())")
private void forDaoPackageNoGetterSetter() {}

www.luv2code.com
Step 3 - Apply Pointcut Declaration to Advice(s)

// combine pointcut: include package ... exclude getter/setter


@Pointcut("forDaoPackage() && !(getter() || setter())")
private void forDaoPackageNoGetterSetter() {}

@Before("forDaoPackageNoGetterSetter()")
public void beforeAddAccountAdvice() {

}

www.luv2code.com
Aspect-Oriented Programming (AOP)
Control Aspect Order
Problem
• How to control the order of advices being applied?

MyLoggingDemoAspect

beforeAddAccountAdvice

performApiAnalyticsAdvice

logToCloudAdvice

www.luv2code.com
Problem
• How to control the order of advices being applied?

MyLoggingDemoAspect

The order is
beforeAddAccountAdvice unde ned

fi
performApiAnalyticsAdvice

logToCloudAdvice

www.luv2code.com
To Control Order
• Refactor: Place advices in separate Aspects

• Control order on Aspects using the @Order annotation

• Guarantees order of when Aspects are applied

www.luv2code.com
Development Process Step-
By-S
tep

1. Refactor: Place advices in separate Aspects

2. Add @Order annotation to Aspects

www.luv2code.com
Step 1 - Refactor: Place advices in separate Aspects

Refactor

www.luv2code.com
Step 2 - Add @Order annotation
• Control order on Aspects using the @Order annotation

@Order(1)
public class MyCloudLogAspect {

}

• Guarantees order of when Aspects are applied

• Lower numbers have higher precedence

www.luv2code.com
@Order
• We want the following order:

1. MyCloudLogAspect

2. MyLoggingDemoAspect

3. MyApiAnalyticsAspect

@Order(1) @Order(2) @Order(3)

Main AOP Target


App Proxy Object

www.luv2code.com
@Order annotation
@Aspect
@Component
@Order(1)
public class MyCloudLogAspect {

} @Aspect
@Component
@Order(2)
public class MyLoggingDemoAspect {

}
@Aspect
@Component
@Order(3)
public class MyApiAnalyticsAspect {

}

www.luv2code.com
@Order annotation
• Lower numbers have higher precedence

• Range: Integer.MIN_VALUE to Integer.MAX_VALUE

• Negative numbers are allowed

• Does not have to be consecutive

@Order(0) @Order(7) @Order(19)

Main AOP Target


App Proxy Object

www.luv2code.com
@Order annotation
• Example with negative numbers

@Order(-40) @Order(-6) @Order(123)

Main AOP Target


App Proxy Object

www.luv2code.com
@Order annotation
• FAQ: What if aspects have the exact same @Order annotation?

@Order(1)
The order at
public class MyCloudLogAspect { … }
this point is
@Order(6) unde ned

fi
public class MyShowAspect { … }

@Order(6)
public class MyFunnyAspect { … } Will still
run AFTER
@Order(123)
MyCloudLogAspect
public class MyLoggingDemoAspect { … }
and BEFORE
MyLoggingDemoAspect
www.luv2code.com
Aspect-Oriented Programming (AOP)
Reading Method Arguments with JoinPoints
Problem
• When we are in an aspect (ie for logging)

• How can we access method parameters?

www.luv2code.com
Development Process Step-
By-S
tep

1. Access and display Method Signature

2. Access and display Method Arguments

www.luv2code.com
Step 1 - Access and display Method Signature

@Before("...")
public void beforeAddAccountAdvice(JoinPoint theJoinPoint) {

www.luv2code.com
Step 1 - Access and display Method Signature

@Before("...")
public void beforeAddAccountAdvice(JoinPoint theJoinPoint) {

// display the method signature


MethodSignature methodSig = (MethodSignature) theJoinPoint.getSignature();

System.out.println("Method: " + methodSig);

www.luv2code.com
Step 2 - Access and display Method Arguments
@Before("...")
public void beforeAddAccountAdvice(JoinPoint theJoinPoint) {

// display method arguments

// get args
Object[] args = theJoinPoint.getArgs();

// loop thru args


for (Object tempArg : args) {
System.out.println(tempArg);
}

www.luv2code.com
Aspect-Oriented Programming (AOP)
Progress Check
Progress Check

Work Completed Work To Do - More Advice Types

• @AfterReturning
• @Before advice type
• @AfterThrowing
• Pointcut Expressions
• @After
• JoinPoints
• @Around

www.luv2code.com
Aspect-Oriented Programming (AOP)
@AfterReturning Advice
Advice Types

• Before advice: run before the method

• After returning advice: run after the method (success execution)

• After throwing advice: run after method (if exception thrown)

• After nally advice: run after the method ( nally)


fi
fi
• Around advice: run before and after method

www.luv2code.com
@AfterReturning Advice - Interaction

Logging Security
Aspect Aspect

TargetObject
@Before
MainApp AOP
Proxy public void doSomeStuff() {
// call target object …
targetObj.doSomeStuff(); @AfterReturning }

Logging Security
Aspect Aspect

www.luv2code.com
Advice - Interaction

@Before

@AfterReturning

Successful execution
(no exceptions)

www.luv2code.com
@AfterReturning Advice - Use Cases
• Most common

• logging, security, transactions

• Audit logging

• who, what, when, where

• Post-processing Data

• Post process the data before returning to caller

• Format the data or enrich the data (really cool but be careful)

www.luv2code.com
Example
• Create an advice that will run after a method call (success execution)

Target Object
AccountDAO
Logging
Aspect

List<Account> ndAccounts()
@AfterReturning

fi
www.luv2code.com
@AfterReturning Advice
• This advice will run after the method call (success execution)

@AfterReturning("execution(* com.luv2code.aopdemo.dao.AccountDAO. ndAccounts(..))")

fi
public void afterReturningFindAccountsAdvice() {

System.out.println("Executing @AfterReturning advice");

www.luv2code.com
Access the Return Value
• Need to access the return value of method called

Target Object
AccountDAO
Logging
Aspect

List<Account> ndAccounts()
@AfterReturning

fi
www.luv2code.com
Access the Return Value

@AfterReturning(
pointcut="execution(* com.luv2code.aopdemo.dao.AccountDAO. ndAccounts(..))",

fi
returning="result")
public void afterReturningFindAccountsAdvice() {

www.luv2code.com
Access the Return Value

@AfterReturning(
pointcut="execution(* com.luv2code.aopdemo.dao.AccountDAO. ndAccounts(..))",

fi
returning="result")
public void afterReturningFindAccountsAdvice(
JoinPoint theJoinPoint, List<Account> result) {

www.luv2code.com
Access the Return Value

@AfterReturning(
pointcut="execution(* com.luv2code.aopdemo.dao.AccountDAO. ndAccounts(..))",

fi
returning="result")
public void afterReturningFindAccountsAdvice(
JoinPoint theJoinPoint, List<Account> result) {

// print out the results of the method call


System.out.println("\n=====>>> result is: " + result);

www.luv2code.com
Best Practices: Aspect and Advices

• Keep the code small

• Keep the code fast

• Do not perform any expensive / slow operations

• Get in and out as QUICKLY as possible

www.luv2code.com
Development Process - @AfterReturning
Step-
By-S
tep
1. Prep Work: Add constructors to Account class

2. Add new method: ndAccounts() in AccountDAO

fi
3. Update main app to call the new method: ndAccounts()

fi
4. Add @AfterReturning advice

www.luv2code.com
Aspect-Oriented Programming (AOP)
@AfterReturning Advice - Modify Return Value
@AfterReturning Advice - Use Cases
• Most common

• logging, security, transactions

• Audit logging

• who, what, when, where

• Post-processing Data

• Post process the data before returning to caller

• Format the data or enrich the data (really cool but be careful)

www.luv2code.com
Post-Process / Modify Data

Target Object
AccountDAO
Logging
Aspect

List<Account> ndAccounts()
@AfterReturning

fi
Post-process the data
(we can modify it)

www.luv2code.com
Modify the Return Value
@AfterReturning(
pointcut="execution(* com.luv2code.aopdemo.dao.AccountDAO. ndAccounts(..))",

fi
returning="result")
public void afterReturningFindAccountsAdvice(
JoinPoint theJoinPoint, List<Account> result) {

// modify “result” list: add, remove, update, etc …

www.luv2code.com
Modify the Return Value
@AfterReturning(
pointcut="execution(* com.luv2code.aopdemo.dao.AccountDAO. ndAccounts(..))",

fi
returning="result")
public void afterReturningFindAccountsAdvice(
JoinPoint theJoinPoint, List<Account> result) {

// modify “result” list: add, remove, update, etc …


if (!result.isEmpty()) {

Account tempAccount = result.get(0);

tempAccount.setName("Daffy Duck");
}
}

www.luv2code.com
Post-Process / Modify Data

Target Object
AccountDAO
Logging
Aspect

List<Account> ndAccounts()
@AfterReturning

fi
Calling program will get the
modified result

www.luv2code.com
Calling program

// call method to nd the accounts

fi
List<Account> theAccounts = theAccountDAO. ndAccounts();

fi
Logging
Aspect

@AfterReturning

Calling program will get the


modified result

www.luv2code.com
Aspect-Oriented Programming (AOP)
@AfterThrowing Advice
Advice Types

• Before advice: run before the method

• After returning advice: run after the method (success execution)

• After throwing advice: run after method (if exception thrown)

• After nally advice: run after the method ( nally)


fi
fi
• Around advice: run before and after method

www.luv2code.com
@AfterThrowing Advice - Interaction

Logging Security
Aspect Aspect

TargetObject
@Before
MainApp AOP
Proxy public void doSomeStuff() {
// call target object …
targetObj.doSomeStuff(); @AfterThrowing } Exception

Logging Security
Aspect Aspect

www.luv2code.com
Advice - Interaction

@Before

Exception

@AfterThrowing

After An Exception is Thrown

www.luv2code.com
Sequence Diagram

www.luv2code.com
@AfterThrowing Advice - Use Cases

• Log the exception

• Perform auditing on the exception

• Notify DevOps team via email or SMS

• Encapsulate this functionality in AOP aspect for easy reuse

www.luv2code.com
Example
• Create an advice that will run after an exception is thrown

Target Object
AccountDAO
Logging
Aspect

List<Account> ndAccounts()
@AfterThrowing

fi
www.luv2code.com
@AfterThrowing Advice
• This advice will run after an exception is thrown

@AfterThrowing("execution(* com.luv2code.aopdemo.dao.AccountDAO. ndAccounts(..))")

fi
public void afterThrowingFindAccountsAdvice() {

System.out.println("Executing @AfterThrowing advice");

www.luv2code.com
Access the Exception object
• Need to access the exception object

Target Object
AccountDAO
Logging
Aspect

List<Account> ndAccounts()
@AfterThrowing

fi
www.luv2code.com
Access the Exception

@AfterThrowing(
pointcut="execution(* com.luv2code.aopdemo.dao.AccountDAO. ndAccounts(..))",

fi
throwing="theExc")
public void afterThrowingFindAccountsAdvice() {

www.luv2code.com
Access the Exception

@AfterThrowing(
pointcut="execution(* com.luv2code.aopdemo.dao.AccountDAO. ndAccounts(..))",

fi
throwing="theExc")
public void afterThrowingFindAccountsAdvice(
JoinPoint theJoinPoint, Throwable theExc) {

www.luv2code.com
Access the Exception

@AfterThrowing(
pointcut="execution(* com.luv2code.aopdemo.dao.AccountDAO. ndAccounts(..))",

fi
throwing="theExc")
public void afterThrowingFindAccountsAdvice(
JoinPoint theJoinPoint, Throwable theExc) {

// log the exception


System.out.println("\n=====>>> The exception is: " + theExc);

www.luv2code.com
Exception Propagation
• At this point, we are only intercepting the exception (reading it)

• However, the exception is still propagated to calling program

www.luv2code.com
Exception Propagation

• If you want to stop the exception propagation

• then use the @Around advice

• covered in later videos

www.luv2code.com
Development Process - @AfterThrowing
Step-
By-S
tep
1. In Main App, add a try/catch block for exception handling

2. Modify AccountDAO to simulate throwing an exception

3. Add @AfterThrowing advice

www.luv2code.com
Aspect-Oriented Programming (AOP)
@After Advice
Advice Types

• Before advice: run before the method

• After returning advice: run after the method (success execution)

• After throwing advice: run after method (if exception thrown)

• After nally advice: run after the method ( nally)


fi
fi
• Around advice: run before and after method

www.luv2code.com
@After (finally) Advice - Interaction

Logging Security
Aspect Aspect

TargetObject
@Before
MainApp AOP
Proxy public void doSomeStuff() {
// call target object …
targetObj.doSomeStuff(); @After ( nally) }

fi
Logging Security
Aspect Aspect

www.luv2code.com
Advice - Interaction

@Before

@After

Runs after a method is Works just like “ nally” block

fi
completed. Regardless of
outcome / exceptions

www.luv2code.com
Sequence Diagram

www.luv2code.com
@After Advice - Use Cases

• Log the exception and/or perform auditing

• Code to run regardless of method outcome

• Encapsulate this functionality in AOP aspect for easy reuse

www.luv2code.com
Example
• Create an advice to run after the method ( nally … success/failure)

fi
Target Object
AccountDAO
Logging
Aspect

List<Account> ndAccounts()
@After

fi
www.luv2code.com
@After Advice
• This advice will run after the method ( nally … success/failure)

fi
@After("execution(* com.luv2code.aopdemo.dao.AccountDAO. ndAccounts(..))")

fi
public void afterFinallyFindAccountsAdvice() {

System.out.println("Executing @After ( nally) advice");

fi
}

www.luv2code.com
@After Advice - Tips

• The @After advice does not have access to the exception

• If you need exception, then use @AfterThrowing advice

• The @After advice should be able to run in the case of success or error

• Your code should not depend on happy path or an exception

• Logging / auditing is the easiest case here

www.luv2code.com
Development Process - @After
Step-
By-S
tep
1. Prep work

2. Add @After advice

3. Test for failure/exception case

4. Test for success case

www.luv2code.com
Aspect-Oriented Programming (AOP)
@Around Advice
Advice Types

• Before advice: run before the method

• After returning advice: run after the method (success execution)

• After throwing advice: run after method (if exception thrown)

• After nally advice: run after the method ( nally)


fi
fi
• Around advice: run before and after method

www.luv2code.com
@Around Advice - Interaction

@Around

Logging TargetObject
MainApp AOP Aspect

Proxy public void doSomeStuff() {


// call target object

targetObj.doSomeStuff();
}

www.luv2code.com
Advice - Interaction

@Around
Logging
Aspect

@Around: Like a combination of @Before and @After

But gives you more fine-grained control

www.luv2code.com
@Around Advice - Use Cases

• Most common: logging, auditing, security

• Pre-processing and post-processing data

• Instrumentation / pro ling code

fi
• How long does it take for a section of code to run?

• Managing exceptions

• Swallow / handle / stop exceptions

www.luv2code.com
Our FortuneService Example - Revisited

Target Object
FortuneService

String getFortune()

www.luv2code.com
Sequence Diagram

www.luv2code.com
ProceedingJoinPoint

• When using @Around advice

• You will get a reference to a “proceeding join point”

• This is a handle to the target method

• Your code can use the proceeding join point to execute target method

www.luv2code.com
Example
• Create an advice for instrumentation / pro ling code

fi
• How long does it take for a section of code to run?

@Around
Logging
Aspect Target Object
FortuneService

String getFortune()

www.luv2code.com
@Around Advice
@Around("execution(* com.luv2code.aopdemo.service.*.getFortune(..))")
public Object afterGetFortune(
ProceedingJoinPoint theProceedingJoinPoint) throws Throwable {

www.luv2code.com
@Around Advice
@Around("execution(* com.luv2code.aopdemo.service.*.getFortune(..))")
public Object afterGetFortune(
ProceedingJoinPoint theProceedingJoinPoint) throws Throwable {

// get begin timestamp


long begin = System.currentTimeMillis();

// now, let's execute the method


Object result = theProceedingJoinPoint.proceed();

// get end timestamp


long end = System.currentTimeMillis();

// compute duration and display it


long duration = end - begin;
System.out.println("\n=====> Duration: " + duration + " milliseconds");

return result;
}

www.luv2code.com
Development Process - @Around
Step-
By-S
tep
1. Create Traf cFortuneService
fi
2. Update main app to call Traf cFortuneService

fi
3. Add @Around advice

www.luv2code.com
Aspect-Oriented Programming (AOP

@Around Advice - Handle Exception


ProceedingJoinPoint - Revisited

• For an exception thrown from proceeding join poin

• You can handle / swallow /stop the exceptio

• Or you can simply rethrow the exception

• This gives you ne-grained control over how the target method is called
fi
www.luv2code.com
Sequence Diagram

www.luv2code.com
Handle Exception
@Around("execution(* com.luv2code.aopdemo.service.*.getFortune(..))"

public Object afterGetFortune

ProceedingJoinPoint theProceedingJoinPoint) throws Throwable

www.luv2code.com
Handle Exception
@Around("execution(* com.luv2code.aopdemo.service.*.getFortune(..))"

public Object afterGetFortune

ProceedingJoinPoint theProceedingJoinPoint) throws Throwable

Object result = null

www.luv2code.com
Handle Exception
@Around("execution(* com.luv2code.aopdemo.service.*.getFortune(..))"

public Object afterGetFortune

ProceedingJoinPoint theProceedingJoinPoint) throws Throwable

Object result = null

try
{

// let's execute the method


result = theProceedingJoinPoint.proceed()

www.luv2code.com
Handle Exception
@Around("execution(* com.luv2code.aopdemo.service.*.getFortune(..))"

public Object afterGetFortune

ProceedingJoinPoint theProceedingJoinPoint) throws Throwable

Object result = null

try
{

// let's execute the method


result = theProceedingJoinPoint.proceed()

} catch (Exception exc)


{

// log exception
System.out.println("@Around advice: We have a problem " + exc)

// handle and give default fortune ... use this approach with caution
result = "Nothing exciting here. Move along!"

www.luv2code.com
Handle Exception
@Around("execution(* com.luv2code.aopdemo.service.*.getFortune(..))"

public Object afterGetFortune

ProceedingJoinPoint theProceedingJoinPoint) throws Throwable

Object result = null

try
{

// let's execute the method


result = theProceedingJoinPoint.proceed()

} catch (Exception exc)


{

// log exception
System.out.println("@Around advice: We have a problem " + exc)

// handle and give default fortune ... use this approach with caution
result = "Nothing exciting here. Move along!"

return result
;
}

www.luv2code.com
Development Process - @Around
Step-
By-S
tep
1. Add trip wire to simulate an exceptio

2. Modify @Around advice to handle exception

www.luv2code.com
Aspect-Oriented Programming (AOP

@Around Advice - Rethrow Exception


ProceedingJoinPoint - Revisited

• For an exception thrown from proceeding join poin

• You can handle / swallow /stop the exceptio

• Or you can simply rethrow the exception

www.luv2code.com
Sequence Diagram

www.luv2code.com
Rethrow Exception
@Around("execution(* com.luv2code.aopdemo.service.*.getFortune(..))"

public Object afterGetFortune

ProceedingJoinPoint theProceedingJoinPoint) throws Throwable

www.luv2code.com
Rethrow Exception
@Around("execution(* com.luv2code.aopdemo.service.*.getFortune(..))"

public Object afterGetFortune

ProceedingJoinPoint theProceedingJoinPoint) throws Throwable

try
{

// let's execute the method


Object result = theProceedingJoinPoint.proceed()

return result;
}

www.luv2code.com
Rethrow Exception
@Around("execution(* com.luv2code.aopdemo.service.*.getFortune(..))"

public Object afterGetFortune

ProceedingJoinPoint theProceedingJoinPoint) throws Throwable

try
{

// let's execute the method


Object result = theProceedingJoinPoint.proceed()

return result;
}

catch (Exception exc)


{

// log exception
System.out.println("@Around advice: We have a problem " + exc)

// rethrow it
throw exc
;

www.luv2code.com
FAQ: JoinPoint vs ProceedingJoinPoint

• When to use JoinPoint vs ProceedingJoinPoint?

• Use JoinPoint with following advice type

• @Before, @After, @AfterReturning, @AfterThrowing

• Use ProceedingJoinPoint with following advice typ

• @Around

www.luv2code.com
Aspect-Oriented Programming (AOP)
AOP and Spring MVC
Goal
• Add AOP Logging support to our Spring MVC CRUD app

www.luv2code.com
Big Picture

1 2 3 4
Employee Employee Employee
Controller Service DAO

Web 5
Browser
Thymeleaf page

www.luv2code.com
Logging Aspect

@Before @Before @Before

Logging Employee Logging Employee Logging Employee


Aspect Controller Aspect Service Aspect DAO

@AfterReturning @AfterReturning @AfterReturning

www.luv2code.com
Development Process Step-
By-S
tep

1. Add Spring Boot AOP Starter to Maven pom le

fi
2. Create Aspect

1. Add logging support

2. Setup pointcut declarations

3. Add @Before advice

4. Add @AfterReturning advice

www.luv2code.com
Step 1: Spring Boot AOP Starter
• Add the dependency for Spring Boot AOP Starter

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>

• Since this dependency is part of our pom.xml

• Spring Boot will automatically enable support for AOP

www.luv2code.com
Development Process Step-
By-S
tep

1. Add Spring Boot AOP Starter to Maven pom le

fi
2. Create Aspect

1. Add logging support

2. Setup pointcut declarations

3. Add @Before advice

4. Add @AfterReturning advice

www.luv2code.com
Pointcut Declarations

Only match on
these three
packages

www.luv2code.com

You might also like