Spring03--AOP aspect oriented programming

1.1 AOP introduction

AOP (aspect oriented programming), aspect oriented programming. Aspect oriented programming is to consider the program running process from a dynamic point of view.
The bottom layer of AOP is realized by dynamic agent mode. Two kinds of agents are used: dynamic agent of JDK and dynamic agent of CGLIB.

AOP is the abbreviation of Aspect Oriented Programming, which means: Aspect Oriented Programming, which can realize the unified maintenance of program functions through runtime dynamic agents. AOP is an important part of the Spring framework. AOP can isolate each part of business logic, reduce the coupling between each part of business logic, improve the reusability of program, and improve the efficiency of development.

Aspect oriented programming is to encapsulate the cross business logic into aspects, and weave the aspects into the main business logic by using the function of AOP container. The so-called cross business logic refers to the common code that has nothing to do with the main business logic, such as security check, transaction, log, cache, etc. If AOP is not used, code entanglement will occur, that is, cross business logic and main business logic are mixed together. In this way, the main business logic will become confused.

1.2 benefits of aspect oriented programming

1. Reduce duplication;
2. Focus on business;

Note: aspect oriented programming is only a supplement to object-oriented programming.

1.3 AOP programming terminology

Aspect

Aspect generally refers to cross business logic. The transaction processing and log processing in the above example can be understood as aspects. A common aspect is Advice. In fact, it is an enhancement to the main business logic.

Join point

Connection point refers to the specific method that can be woven by cutting. Generally, the methods in the business interface are connection points.

Pointcut

A pointcut is a collection of one or more declared join points. Specify a set of methods through pointcuts. Methods marked final cannot be used as join points and pointcuts. Because the final can not be modified, can not be enhanced.

Target object

The target object is the object to be enhanced. That is, the object of the class containing the main business logic.

Advice

The notification indicates the execution time of the aspect, and Advice is also called enhancement. In other words, notification defines the time point when the enhanced code cuts into the target code, whether it is executed before or after the execution of the target method. Different notification types lead to different cut in times. The pointcut defines the position of the pointcut and notifies the time of the pointcut.

1.4 implementation of AOP by AspectJ

For the programming idea of AOP, many frameworks have been implemented. Spring is one of them, which can complete aspect oriented programming. However, AspectJ also implements the function of AOP, and its implementation method is simpler, more convenient to use, and also supports annotated development. Therefore, spring also introduces AspectJ's implementation of AOP into its own framework.

When using AOP development in Spring, the implementation of AspectJ is generally used.

Introduction to AspectJ

AspectJ is an excellent aspect oriented framework, which extends the Java language and provides a powerful aspect implementation.

1.4.1 notification type of AspectJ

There are five types of notifications commonly used in AspectJ:
(1) Advance notice
(2) Post notification
(3) Surround notification
(4) Exception notification
(5) Final notice

1.4.2 pointcut expression of AspectJ

AspectJ defines special expressions for specifying pointcuts. The prototype of the expression is:

execution(modifiers-pattern? 
			ret-type-pattern declaring-type-pattern?name-pattern(param-pattern) 
			throws-pattern?)

Modifiers pattern access type
RET type pattern return value type
Declaring type pattern package name class name
Name pattern (param pattern) method name (parameter type and number of parameters)
Throws pattern throw exception type
? Represents an optional part

The above expression consists of four parts.
Execution (access permission method return value method declaration (parameter) exception type)
The object to be matched by the pointcut expression is the method name of the target method. Therefore, the execution expression is obviously the signature of the method. Note that the black bold text in the expression indicates the parts that can be omitted, and the parts are separated by spaces. The following symbols can be used:

Symbolsignificance
*0 cannot contain more than any characters
...Used in parameter method to represent any number of parameters; Used after the package name to indicate the path of the current package and its sub packages.
+Used after the class name to represent the current class and its subclasses; Used after an interface to represent the current interface and its implementation class.

1.4.3 AspectJ development environment

1) maven dependency

<dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <!--spring rely on-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.2.5.RELEASE</version>
    </dependency>
    <!--aspectj rely on-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aspects</artifactId>
      <version>5.2.5.RELEASE</version>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.1</version>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
    </plugins>
  </build>

2) Introducing AOP constraints

When AspectJ implements AOP, AOP constraints should be introduced. The tags in the AOP constraints used in the configuration file are used by the AspectJ framework, not by the Spring framework itself when implementing AOP.
AspectJ has two ways to implement AOP: annotation and configuration file. Annotation is commonly used.

1.4.4 AspectJ annotation based AOP implementation

1) Advance notice

Test interface:

public interface SomeService {
    void doSome(String name,Integer age);
}

Interface implementation class:

public class SomeServiceImpl implements SomeService {
    @Override
    public void doSome(String name,Integer age) {
        //Add a function to the doSome method to output the execution time of the method before the execution of doSome()
        System.out.println("====Target method doSome()====");
    }
}

Section class:

/**
 *  @Aspect : Is an annotation in the aspectj framework.
 *     Function: indicates that the current class is a faceted class.
 *     Aspect class: a class used to add functions to business methods. In this class, there are aspect function codes
 *     Location: above the class definition
 */
@Aspect
public class MyAspect {
    /**
     * @Before: Pre notification annotation
     *   Attribute: value, is the pointcut expression, indicating the execution position of the function of the aspect.
     *   Location: above the method
     * characteristic:
     *  1.Executed before the target method
     *  2.The execution result of the target method will not be changed
     *  3.It will not affect the execution of the target method.
     */
   @Before(value = "execution(public void com.suyv.spring.ba01.SomeServiceImpl.doSome(String,Integer))")
    public void myBefore(){
        //Is the function code you want to execute
        System.out.println("Pre notification, aspect function: output the execution time before the target method:"+ new Date());
    }

spring configuration file:

	<!--Declare target object-->
    <bean id="someService" class="com.suyv.spring.ba01.SomeServiceImpl" />
    <!--Declare facet class objects-->
    <bean id="myAspect" class="com.suyv.spring.ba01.MyAspect" />
    <!--Declaring automatic proxy generators: Using aspectj The function inside the framework creates the proxy object of the target object.
        Creating a proxy object is implemented in memory and modifying the structure in memory of the target object. 
        Created as a proxy object, so the target object is the modified proxy object.
        aspectj-autoproxy:Will put spring All target objects in the container generate proxy objects at one time.
    -->
    <aop:aspectj-autoproxy />

Test method:

	@Test
    public void test01(){
        String config="applicationContext.xml";
        ApplicationContext ctx = new ClassPathXmlApplicationContext(config);
        //Get target object from container
        SomeService proxy = (SomeService) ctx.getBean("someService");
        System.out.println("proxy:"+proxy.getClass().getName());
        //Through the object execution method of the agent, the function is enhanced when the target method is executed
        proxy.doSome("lisi",20);
    }

Test results:

2) Post notification

Test interface:

public interface SomeService {
    void doSome(String name, Integer age);
    String doOther(String name,Integer age);
}

Interface implementation class:

public class SomeServiceImpl implements SomeService {

    @Override
    public void doSome(String name,Integer age) {
        //Add a function to the doSome method to output the execution time of the method before the execution of doSome()
        System.out.println("====Target method doSome()====");
    }

    @Override
    public String doOther(String name, Integer age) {
        System.out.println("====Target method doOther()====");
        return "abcd";
    }

}

Section class:

@Aspect
public class MyAspect {
    /**
     * @AfterReturning:Post notification
     *    Attribute: 1 Value pointcut expression
     *         2.returning A custom variable that represents the return value of the target method.
     *          The custom variable name must be the same as the formal parameter name of the notification method.
     *    Location: above the method definition
     * characteristic:
     *  1. Executed after the target method.
     *  2. The return value of the target method can be obtained, and different processing functions can be performed according to the return value
     *      Object res = doOther();
     *  3. You can modify the return value
     */
    @AfterReturning(value = "execution(* *..SomeServiceImpl.doOther(..))",
                    returning = "res")
    public void myAfterReturing(  JoinPoint jp  ,Object res ){
        // Object res: is the return value of the target method after execution. Do the function processing of your aspect according to the return value
        System.out.println("Post notification: method definition"+ jp.getSignature());
        System.out.println("Post notification: executed after the target method, the returned value obtained is:"+res);
        if(res.equals("abcd")){
            //Do some functions
        } else{
            //Do other functions
        }
        //Modify the return value of the target method to see if it will affect the final method call result
        if( res != null){
            res = "Hello Aspectj";
        }

    }
    
}

spring configuration file:

    <!--Declare target object-->
    <bean id="someService" class="com.suyv.spring.ba02.SomeServiceImpl" />
    <!--Declare facet class objects-->
    <bean id="myAspect" class="com.suyv.spring.ba02.MyAspect" />
    <!--Declare automatic proxy generator-->
    <aop:aspectj-autoproxy />

Test method:

    @Test
    public void test01(){
        String config="applicationContext.xml";
        ApplicationContext ctx = new ClassPathXmlApplicationContext(config);
        //Get target object from container
        SomeService proxy = (SomeService) ctx.getBean("someService");
        //Through the object execution method of the agent, the function is enhanced when the target method is executed
        String str = proxy.doOther("zs",28);
        System.out.println("str===="+str);

    }

Test results:

3) Surround notification

Test interface:

public interface SomeService {
    void doSome(String name, Integer age);
    String doOther(String name, Integer age);
    String doFirst(String name,Integer age);
}

Interface implementation class:

public class SomeServiceImpl implements SomeService{
    @Override
    public void doSome(String name,Integer age) {
        //Add a function to the doSome method to output the execution time of the method before the execution of doSome()
        System.out.println("====Target method doSome()====");
    }

    @Override
    public String doOther(String name, Integer age) {
        System.out.println("====Target method doOther()====");
        return "abcd";
    }

    @Override
    public String doFirst(String name, Integer age) {
        System.out.println("====Business method doFirst()====");

        return "doFirst";
    }
}

Section class:

@Aspect
public class MyAspect {
    /**
     * @Around: Around Advice 
     *    Attribute: value pointcut expression
     *    Location: what is the definition of the method
     * characteristic:
     *   1.It is the most powerful notification
     *   2.Enhancements can be made before and after the target method.
     *   3.Controls whether the target method is called and executed
     *   4.Modify the execution result of the original target method. Affect the final call result
     */
    @Around(value = "execution(* *..SomeServiceImpl.doFirst(..))")
    public Object myAround(ProceedingJoinPoint pjp) throws Throwable {
        String name = "";
        //Get the first parameter value
        Object args [] = pjp.getArgs();
        if( args!= null && args.length > 1){
            Object arg=  args[0];
            name =(String)arg;
        }
        //Implement surround notification
        Object result = null;
        System.out.println("Surround notification: before the target method, output time:"+ new Date());
        //1. Target method call
        if( "zhangsan".equals(name)){
            //If the conditions are met, call the target method
            result = pjp.proceed(); //method.invoke(); Object result = doFirst();
        }
        System.out.println("Surround notification: commit the transaction after the target method");
        //2. Add functions before or after the target method
        //Modify the execution result of the target method and affect the final call result of the method
        if( result != null){
            result = "Hello AspectJ AOP";
        }
        //Returns the execution result of the target method
        return result;
    }
}

spring configuration file:

	<!--Declare target object-->
    <bean id="someService" class="com.suyv.spring.ba03.SomeServiceImpl" />
    <!--Declare facet class objects-->
    <bean id="myAspect" class="com.suyv.spring.ba03.MyAspect" />
    <!--Declare automatic proxy generator-->
    <aop:aspectj-autoproxy />

Test method:

@Test
    public void test01(){
        String config="applicationContext.xml";
        ApplicationContext ctx = new ClassPathXmlApplicationContext(config);
        //Get target object from container
        SomeService proxy = (SomeService) ctx.getBean("someService");
        //Through the object execution method of the agent, the function is enhanced when the target method is executed
        String str = proxy.doFirst("zhangsan",20); /// myAround()
    }

Test results:

4) Exception notification

Test interface:

public interface SomeService {
    void doSome(String name, Integer age);
    String doOther(String name, Integer age);
    String doFirst(String name, Integer age);
    void doSecond();
}

Interface implementation class:

//Target class
public class SomeServiceImpl implements SomeService {
    @Override
    public void doSome(String name,Integer age) {
        //Add a function to the doSome method to output the execution time of the method before the execution of doSome()
        System.out.println("====Target method doSome()====");
    }

    @Override
    public String doOther(String name, Integer age) {
        System.out.println("====Target method doOther()====");
        return "abcd";
    }

    @Override
    public String doFirst(String name, Integer age) {
        System.out.println("====Business method doFirst()====");
        return "doFirst";
    }

    @Override
    public void doSecond() {
        System.out.println("Business execution method doSecond()" + (10/0));
    }
}

Section class:

@Aspect
public class MyAspect {
    /**
     * @AfterThrowing:Exception notification
     *     Attribute: 1 Value pointcut expression
     *          2. throwinng A custom variable that represents the exception object thrown by the target method.
     *             The variable name must be the same as the parameter name of the method
     * characteristic:
     *   1. Executed when the target method throws an exception
     *   2. An exception monitoring program can be used to monitor whether there are exceptions when the target method is executed.
     *      If there is any abnormality, you can send e-mail and SMS for notification
     */
    @AfterThrowing(value = "execution(* *..SomeServiceImpl.doSecond(..))",
            throwing = "ex")
    public void myAfterThrowing(Exception ex) {
        System.out.println("Exception notification: when an exception occurs in the method, execute:"+ex.getMessage());
    }
}

spring configuration file:

	<!--Declare target object-->
    <bean id="someService" class="com.suyv.spring.ba04.SomeServiceImpl" />
    <!--Declare facet class objects-->
    <bean id="myAspect" class="com.suyv.spring.ba04.MyAspect" />
    <!--Declare automatic proxy generator-->
    <aop:aspectj-autoproxy />

Test method:

	@Test
    public void test01(){
        String config="applicationContext.xml";
        ApplicationContext ctx = new ClassPathXmlApplicationContext(config);
        //Get target object from container
        SomeService proxy = (SomeService) ctx.getBean("someService");
        //Through the object execution method of the agent, the function is enhanced when the target method is executed
        proxy.doSecond();
    }

Test results:

5) Final notice

Test interface:

public interface SomeService {
    void doSome(String name, Integer age);
    String doOther(String name, Integer age);
    String doFirst(String name, Integer age);
    void doSecond();
    void doThird();
}

Interface implementation class:

public class SomeServiceImpl implements SomeService {
    @Override
    public void doSome(String name,Integer age) {
        //Add a function to the doSome method to output the execution time of the method before the execution of doSome()
        System.out.println("====Target method doSome()====");
    }

    @Override
    public String doOther(String name, Integer age) {
        System.out.println("====Target method doOther()====");
        return "abcd";
    }
    
    @Override
    public String doFirst(String name, Integer age) {
        System.out.println("====Business method doFirst()====");
        return "doFirst";
    }

    @Override
    public void doSecond() {
        System.out.println("Execute business methods doSecond()" + (10/0));
    }

    @Override
    public void doThird() {
        System.out.println("Execute business methods doThird()"+ (10/0));
    }

}

Section class:

@Aspect
public class MyAspect {
    /**
     * @After :Final notice
     *    Attribute: value pointcut expression
     *    Location: above the method
     * characteristic:
     *  1.Always execute
     *  2.Executed after the target method
     */
    @After(value = "execution(* *..SomeServiceImpl.doThird(..))")
    public  void  myAfter(){
        System.out.println("Code that will always be executed when the final notification is executed");
     }
}

spring configuration file:

	<!--Declare target object-->
    <bean id="someService" class="com.suyv.spring.ba05.SomeServiceImpl" />
    <!--Declare facet class objects-->
    <bean id="myAspect" class="com.suyv.spring.ba05.MyAspect" />
    <!--Declare automatic proxy generator-->
    <aop:aspectj-autoproxy />

Test method:

	@Test
    public void test01(){
        String config="applicationContext.xml";
        ApplicationContext ctx = new ClassPathXmlApplicationContext(config);
        //Get target object from container
        SomeService proxy = (SomeService) ctx.getBean("someService");
        //Through the object execution method of the agent, the function is enhanced when the target method is executed
        proxy.doThird();
    }

Test results:

1.5 implementation of AOP by cglib

Test interface:

public interface SomeService {
    void doSome(String name,Integer age);
}

Interface implementation class:

public class SomeServiceImpl implements SomeService {
    @Override
    public void doSome(String name,Integer age) {
        //Add a function to the doSome method to output the execution time of the method before the execution of doSome()
        System.out.println("====Target method doSome()====");
    }
}

Section class:

@Aspect
public class MyAspect {
   @Before(value = "execution(public void com.suyv.spring.ba01.SomeServiceImpl.doSome(String,Integer))")
    public void myBefore(){
        //Is the function code you want to execute
        System.out.println("Pre notification, aspect function: output the execution time before the target method:"+ new Date());
    }

spring configuration file:

	<!--Declare target object-->
    <bean id="someService" class="com.suyv.spring.ba01.SomeServiceImpl" />
    <!--Declare facet class objects-->
    <bean id="myAspect" class="com.suyv.spring.ba01.MyAspect" />
    <!--
       If you expect the target class to have an interface, use cglib agent
       proxy-target-class="true":Tell the framework to use cglib Dynamic agent
    -->
    <aop:aspectj-autoproxy proxy-target-class="true"/>

Test method:

	@Test
    public void test01(){
        String config="applicationContext.xml";
        ApplicationContext ctx = new ClassPathXmlApplicationContext(config);
        //Get target object from container
        SomeService proxy = (SomeService) ctx.getBean("someService");
        System.out.println("proxy:"+proxy.getClass().getName());
        //Through the object execution method of the agent, the function is enhanced when the target method is executed
        proxy.doSome("lisi",20);
    }

Test results:

Keywords: Java Spring SSM

Added by mrjam on Wed, 19 Jan 2022 20:10:31 +0200