AOP: Section-oriented programming, as opposed to OOP object-oriented programming 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 inherited singly, preventing more behavior from being added to a set of classes. AOP makes up for OOP.

And for the sake of clear logic, let the business logic focus on the business itself and not on other things, such as transactions.

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

AOP terminology:

Aop has a lot of jargon that is very difficult to understand, so let me explain it briefly

  • Advice (sometimes called enhancement)

    The work that needs to be done is called notification and is defined in the business logic that you write, such as transactions, logs, etc., and then used where needed

  • Join point

    This is where spring allows you to use notifications, and basically every method that throws an exception before and after can be a join point

  • Point of contact (Poincut)

    All methods in a class are join points, but not all of them are needed. Some of them are selected as join points as pointcuts. If the advice defines the action or timing of the cut, the cut point defines the place of execution

  • Section (Aspect)

    It’s basically a combination of the advice and the pointcut, and the advice and pointcut together define all the content of the aspect, what does it do, when and where does it do it

  • Introduction (the Introduction)

    Adding properties and methods to an existing class without changing its code can give them new behavior and state without modifying existing classes. This is to apply the aspect (defined by the new method property: notification) to the target class

  • The target (target)

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

  • Weave (has)

    The process of adding facets to program code. Facets are woven into the target object at the specified join point, and there are multiple points that can be woven into the target object during its lifetime:

    • Compile-time: The aspect is woven in when the target class is compiled, which requires a special compiler
    • Class loading time: The aspect is woven into the target class when it is loaded into the JVM. This approach requires a special class loader that enhances the bytecode of the target class before it is introduced into the application
    • Runtime: The aspect is woven at some point during the application’s run. Typically, when weaving into the aspect, the AOP container dynamically creates a proxy object for the target object, which is how Spring AOP is woven into the aspect.

Ex. :

public class UserService{
    void save(a){}
    List list(a){}... }Copy the code

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

So, all methods in UserService are joinpoints, and the save() method is Poincut. The method that needs to be executed before and after the save() method is Advice, and pointcuts and Advice together are an Aspect. The save() method is the target. Weaving is the method that dynamically adds the code you want to execute to and from the save() method.

In some places it makes sense to call advice an enhancement, and adding other methods before and after a business method is an enhancement to that method.

Common AOP notification (enhanced) types

  • Before: Executed before method execution begins
  • After (post-notification) : executed after method execution
  • AfterReturning (notification after return) : Executed after a method returns
  • AfterThrowing: Executed when an exception is thrown
  • Around: Before and after a method is executed

Three, the order of execution

around > before > around > after > afterReturning

Four, first say SpringAop is very domineer and use very few features — Introduction

  1. The configuration class
@Aspect
@Component
public class IntroductionAop {

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

}
Copy the code
  1. The service code
public interface DoSthService {

    void doSth(a);
}

@Service
public class DoSthServiceImpl implements DoSthService {

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

    void testIntroduction(a);
}

@Service
public class UserServiceImpl implements UserService {

    @Override
    public void testIntroduction(a) {
        System.out.println("do testIntroduction"); }}Copy the code
  1. The test code
@Test
public void testIntroduction(a) {
    userService.testIntroduction();
    //Aop lets the UserService method have the DoSthService method
    DoSthService doSthService = (DoSthService) userService;
    doSthService.doSth();
}
Copy the code
  1. The results of
do testIntroduction
do sth ....
Copy the code

Five or five notification (enhanced) code implementations

  1. The configuration class

(1) the method

@Aspect
@Component
public class TransactionAop {

    @Pointcut("execution(* com.jiuxian.. service.*.*(..) )")
    public void pointcut(a) {}@Before("pointcut()")
    public void beginTransaction(a) {
        System.out.println("before beginTransaction");
    }

    @After("pointcut()")
    public void commit(a) {
        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(a) {
        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"); }}}Copy the code

(2) the annotation

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Log {
    String value(a) default "";
}
Copy the code
@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(Annotated interception + log.value());
    }
Copy the code
  1. Service method implementation
public interface UserService {

    String save(String user);

    void testAnnotationAop(a);
}


@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(a) {
        System.out.println("testAnnotationAop"); }}Copy the code
  1. The test class
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootAopApplicationTests {

    @Resource
    private UserService userService;

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

    @Test
    public void testAop2(a) {
        userService.save("a");
    }
    
    @Test
    public void testAop3(a) { userService.testAnnotationAop(); }}Copy the code
  1. The results of
  • When performing a testAop1
Around before beginTransaction Saves user information around after Commit afterReturning :: Zhang3Copy the code
  • When performing a testAop2
Around before beginTransaction Saves user information around After COMMIT afterThrowing rollbackCopy the code
  • When performing a testAop3
test
around
testAnnotationAop
around
Copy the code
  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>
Copy the code

Execution

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

  • The body of an execution expression
  • The first * represents any return value
  • Com. jiuxian aop crosscutting package name
  • The package back.. Represents the current package and its subpackages
  • The second * represents the class name, representing all classes
  • . * (..) Represents any method, and the parentheses represent arguments.. Represents any parameter

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

The tangency of a method whose class name ends with service, method name begins with add, and parameter type is String in the com.jiuxian package and its subpackage service package.

7. Special Usage

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

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

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

Can use &&, | |,! Operator to define the pointcut

Viii. For more details, please refer to the official website

SpringAOP official website introduction

Nine, this article sample code

Making the source code

The above code is based on Springboot 2.0