Use of Spring Boot AOP

Change from: https://www.jianshu.com/p/4d22ea402d14

AOP: aspect oriented programming, as opposed to OOP
Spring's AOP exists for decoupling. AOP allows a set of classes to share the same behavior. In OOP, only interfaces can be inherited and implemented, and class inheritance can only be single inheritance, which prevents more behaviors from being added to a group of classes. AOP makes up for the shortage of OOP.

The other is to make the business logic focus on the business itself and not on other things, such as transactions, for the sake of clear logic.

Spring's AOP is implemented through JDK's dynamic proxy and CGLIB.

1, AOP terminology:

aop has a lot of terms, which are very difficult to understand. Let's simply say that

  • Notice (some places are called Advice)

    What needs to be done is called notification, which means that the business logic you write, such as transaction and log, needs to be defined first and then used where it needs to be

  • Join point

    This is where notification is allowed in spring. Basically, every method can be a join point when throwing exceptions back and forth

  • Poicut

    In fact, it is the filtered join points. All methods in a class are join points, but they are not all needed. Some will be filtered as join points as tangent points. If the notification defines the action or execution time of the tangent, the tangent defines the execution place

  • Aspect (Aspect)

    In fact, it is the combination of notification and pointcut. Notification and pointcut jointly define all the content of the pointcut, what it does, when and where to execute it

  • Introduction

    Without changing an existing class code, adding properties and methods to the class can make them have new behavior and state without modifying the existing class. In fact, the aspect (that is, the new method attribute: notification defined) is used in the target class

  • Target

    The notified object. That is, the objects that need to be added additional code, that is, the real business logic is organized into aspects.

  • Weaving

    The process of adding facets to program code. The tangent is woven into the target object at the specified connection point, and there are multiple points that can be woven in the target object's life cycle:

    • Compile time: facets are woven into the target class at compile time, which requires a special compiler
    • Class loading period: facets are woven when the target class is loaded into the JVM. This method requires a special class loader, which can enhance the bytecode of the target class before it is introduced into the application
    • Runtime: facets are woven in at a certain time when the application is running. Generally, when weaving facets, the AOP container will dynamically create a proxy object for the target object. Spring AOP weaves facets in this way.

Example:

 

public class UserService{
    void save(){}
    List list(){}
    ....
}

The transaction needs to be opened before the save() method in UserService, closed after the method, and rolled back when throwing an exception.

Then, all methods in UserService are join points, and the save() method is poincut. The method that needs to be executed before and after the save() method is advice, and the pointcut and the notification are an aspect. The save() method is the target. Adding the code you want to execute dynamically before and after the save() method is weaving.

In some places, it makes sense to call notifications enhancements. Adding other methods before and after a business method is actually an enhancement of that method.

2, Common AOP notification (enhanced) types

  • Before: execute before method execution
  • After: after method execution
  • After returning: executes after the method returns
  • After throwing: executed when an exception is thrown
  • Around: executes before and after method execution

3, Execution sequence

around > before > around > after > afterReturning

4, First of all, spring AOP is very aggressive and uses very few functions -- introduction

  1. Configuration class

 

@Aspect
@Component
public class IntroductionAop {

    @DeclareParents(value = "com.jiuxian..service..*", defaultImpl = DoSthServiceImpl.class)
    public DoSthService doSthService;

}
  1. service code

 

public interface DoSthService {

    void doSth();
}

@Service
public class DoSthServiceImpl implements DoSthService {

    @Override
    public void doSth() {
        System.out.println("do sth ....");
    }
    
}

public interface UserService {

    void testIntroduction();
}

@Service
public class UserServiceImpl implements UserService {

    @Override
    public void testIntroduction() {
        System.out.println("do testIntroduction");
    }
}
  1. Test code

 

@Test
public void testIntroduction() {
    userService.testIntroduction();
    //Aop let UserService method have DoSthService method
    DoSthService doSthService = (DoSthService) userService;
    doSthService.doSth();
}
  1. Result

 

do testIntroduction
do sth ....

5, Five kinds of notification (enhanced) code implementation

  1. Configuration class

(1) Right method

 

@Aspect
@Component
public class TransactionAop {

    @Pointcut("execution(* com.jiuxian..service.*.*(..))")
    public void pointcut() {
    }

    @Before("pointcut()")
    public void beginTransaction() {
        System.out.println("before beginTransaction");
    }

    @After("pointcut()")
    public void commit() {
        System.out.println("after commit");
    }

    @AfterReturning("pointcut()", returning = "returnObject")
    public void afterReturning(JoinPoint joinPoint, Object returnObject) {
        System.out.println("afterReturning");
    }

    @AfterThrowing("pointcut()")
    public void afterThrowing() {
        System.out.println("afterThrowing afterThrowing  rollback");
    }

    @Around("pointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        try {
            System.out.println("around");
            return joinPoint.proceed();
        } catch (Throwable e) {
            e.printStackTrace();
            throw e;
        } finally {
            System.out.println("around");
        }
    }
}

(2) Comment on

 

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Log {
    String value() default "";
}

 

@Aspect
@Component
public class AnnotationAop {

    @Pointcut(value = "@annotation(log)", argNames = "log")
    public void pointcut(Log log) {
    }

    @Around(value = "pointcut(log)", argNames = "joinPoint,log")
    public Object around(ProceedingJoinPoint joinPoint, Log log) throws Throwable {
        try {
            System.out.println(log.value());
            System.out.println("around");
            return joinPoint.proceed();
        } catch (Throwable throwable) {
            throw throwable;
        } finally {
            System.out.println("around");
        }
    }
}
  @Before("@annotation(com.jiuxian.annotation.Log)")
  public void before(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        Log log = method.getAnnotation(Log.class);
        System.out.println("Comment block " + log.value());
    }
  1. service method implementation

 

public interface UserService {

    String save(String user);

    void testAnnotationAop();
}


@Service
public class UserServiceImpl implements UserService {

    @Override
    public String save(String user) {
        System.out.println("Save user information");
        if ("a".equals(user)) {
            throw new RuntimeException();
        }
        return user;
    }

    @Log(value = "test")
    @Override
    public void testAnnotationAop() {
        System.out.println("testAnnotationAop");
    }
}
  1. Test class

 

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootAopApplicationTests {

    @Resource
    private UserService userService;

    @Test
    public void testAop1() {
        userService.save("Zhang San");
        Assert.assertTrue(true);
    }

    @Test
    public void testAop2() {
        userService.save("a");
    }
    
    @Test
    public void testAop3() {
        userService.testAnnotationAop();
    }
}
  1. Result
  • When testAop1 is executed

 

around
before beginTransaction
 Save user information
around
after commit
 afterReturning: Zhang San
  • When testAop2 is executed

 

around
before beginTransaction
 Save user information
around
after commit
afterThrowing  rollback
  • When testAop3 is executed

 

test
around
testAnnotationAop
around
  1. pom file

 

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

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

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

6, The most commonly used execution explanation

Example: execution(* com.jiuxian..service. *. * (..))

  • Body of execution expression
  • The first * represents any return value
  • Package name crosscut by com.jiuxian aop
  • After the package.. indicates the current package and its children
  • The second * represents the class name, representing all classes
  • . * (..) for any method, parentheses for parameters.. for any parameter

Example: execution(* com.jiuxian..service.*Service.add*(String))

Representation: under the service package of com.jiuxian package and its sub package, the class name ends with service, the method starts with add, and the parameter type is the tangent point of the method with String.

7, Special usage

 

@Pointcut("execution(public * *(..))")
private void anyPublicOperation() {} 

@Pointcut("within(com.xyz.someapp.trading..*)")
private void inTrading() {} 

@Pointcut("anyPublicOperation() && inTrading()")
private void tradingOperation() {}

You can use the & &, |,! Operators to define the tangent point

8, For more details, please refer to the official website

Spring AOP official website introduction

9, Sample code of this article

GitHub source code

Published 8 original articles, won praise 102, and visited 390000+
Private letter follow

Tags: Spring Programming JDK Attribute

Posted on Tue, 04 Feb 2020 06:43:13 -0500 by jossejf