Spring AOP aspect oriented programming

Spring AOP

Aspect oriented programming aims to encapsulate those operations that have nothing to do with business but are common to business modules (such as logging), so as to reduce system duplication of code and reduce system coupling.

Application scenario:

  • Logging
  • Permission control
  • transaction management

Underlying implementation principle

  • JDK dynamic proxy -- the premise is that the class implements the interface
  • CGLIB agent

Relationship between Spring AOP and AspectJ

  • Both are to implement AOP, which is based on dynamic proxy, and AspectJ is based on bytecode operation
  • AOP is a runtime enhancement
  • AspectJ is a compile time enhancement

If there are not many facets, there is not much performance difference between the two
AspectJ will be much faster if there are many facets


Some concepts in AOP

notice

When and what to do during method execution

  • Pre Notification - operations to be performed before method execution
  • Post Notification - action to be performed after method execution
  • Return Notification - the operation to be performed after the method is successfully executed
  • Exception Notification - the operation to be performed after a method throws an exception
  • Surround Notification - custom operations should be performed before and after method execution

Connection point

It can be when a method is called or after an exception is thrown. It is always the front and back of the method. It is the connection point

breakthrough point

If a class has 10 methods, then there are 10 pointcuts

section

The combination of notification and entry point. In popular terms, notification indicates when to do + what to do, and entry point indicates where to do

illustrate

In order to explain the concept of AOP more conveniently, here is an example in life

It can be seen that the main business of the chartering company is to sign contracts and collect rent. That's enough. The parts framed in purple are all repetitive things. Just give them to the intermediary.
This is the idea of AOP: separation of core business code and focus code

Actual code

You can't just talk but practice. Let's experience the actual code

XMl based Demo

1. import dependency

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.0.7.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.5</version>
        </dependency>
    </dependencies>

2. create a Landlord class under the pojo package (Landlord ≈ charterer)

package jay.pojo;

import org.springframework.stereotype.Component;

/**
 * @author Jaychan
 * @date 2020/7/10
 * @description TODO
 */

@Component("landlord")
public class Landlord {

 	  public void service(){
        //Only core business functions are realized
        System.out.println("Sign a contract");
        System.out.println("Rent collection");
        
    }
}

3. create a Broker class (intermediary) under the aspect package

package jay.aspect;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;



@Component
@Aspect
class Broker {

	//Tell spring how to intercept
	//A cut-off point is customized to reduce the number of expressions and avoid code redundancy
    @Pointcut("execution(* jay.pojo.Landlord.service())")
    public void lService() {
    }

    @Before("lService()")
    public void before() {
        System.out.println("Show the tenant");
        System.out.println("Talk about price");
    }

    @After("lService()")
    public void after() {
        System.out.println("Turnkey");
    }
}

4. in applicationcontext Configure automatic injection in XML to tell ioc container where to scan these two bean s

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <context:component-scan base-package="aspect" />
    <context:component-scan base-package="pojo" />

    <aop:aspectj-autoproxy/>
</beans>

5. writing test classes

package test;

import org.springframework.context.support.ClassPathXmlApplicationContext;
import pojo.Landlord;

/**
 * @author Jaychan
 * @date 2020/7/10
 * @description TODO
 */
public class TestSpring {

    public static void main(String[] args) {

        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

        Landlord landlord = context.getBean("landlord", Landlord.class);
        
        landlord.service();

    }

}

6. operation results

July 10, 2020 3:19:52 afternoon org.springframework.context.support.AbstractApplicationContext prepareRefresh
 information: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@23ab930d: startup date [Fri Jul 10 15:19:52 CST 2020]; root of context hierarchy
 July 10, 2020 3:19:52 afternoon org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
 information: Loading XML bean definitions from class path resource [applicationContext.xml]
Show the tenant
 Talk about price
 Sign a contract
 Rent collection
 Turnkey

Process finished with exit code 0




Annotation based Demo


Step 1: select the connection point

Spring is a method level AOP framework that can be specific to a method of a class as a connection point. Another way is to choose which method of that kind to enhance the function.

@Component("landlord")
public class Landlord {


    public void service(){
        //Only core business functions are realized
        System.out.println("Sign a contract");
        System.out.println("Rent collection");
    }

}

We choose Landlord's service() method as the connection point



Step 2: create cut plane

After selecting the connection point, you can create the section. We can understand the aspect as an interceptor. When the program runs to the connection point, it will be intercepted. An initialization method will be executed at the beginning and a destruction method will be added at the end.
In Spring, as long as you annotate a class with * * @Aspect**, the SpringIoc container will consider this as an Aspect. At the same time, remember to add the @component tag to the Spring Ioc container.

package jay.aspect;


import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;



@Component
@Aspect
class Broker {

    @Pointcut("execution(* jay.pojo.Landlord.service())")
    public void lService() {
    }

    @Before("lService()")
    public void before() {
        System.out.println("Show the tenant");
        System.out.println("Talk about price");
    }

    @After("lService()")
    public void after() {
        System.out.println("Turnkey");
    }
}


Step 3: define the tangent point

The above annotation defines the regular expression of execution. Spring uses this regular expression to determine which method of which class to intercept:

execution(* jay.pojo.Landlord.service())

Analyze this expression in turn:

execution: triggered when the method is executed

*: method representing any return type
Jay Pojo Landlord: the fully qualified name of the representative class
service(): name of the intercepted method



Step 4: write the aopconfig configuration class

The main functions of this class are
Using JDK dynamic proxy
Tell the SpringIoc container to scan the classes under that package

@Configuration
@ComponentScan("jay")
@EnableAspectJAutoProxy   //(proxyTargetClass = true) 
						 //If true, the cglib implementation will be used
public class AopConfig {
}


Step 5: write a test class

package jay;

import jay.config.AopConfig;
import jay.pojo.Landlord;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @author Jaychan
 * @date 2020/7/10
 * @description TODO
 */
public class TestSpring {

    public static void main(String[] args) {

        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AopConfig.class);

        Landlord bean = context.getBean(Landlord.class);

        bean.service();

    }
}

Output results

July 10, 2020 3:26:13 afternoon org.springframework.context.support.AbstractApplicationContext prepareRefresh
 information: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@2d38eb89: startup date [Fri Jul 10 15:26:13 CST 2020]; root of context hierarchy
 Show the tenant
 Talk about price
 Sign a contract
 Rent collection
 Turnkey

Process finished with exit code 0

Tags: Java Spring AOP

Posted by headmine on Tue, 31 May 2022 19:35:40 +0530