Basic steps of implementing aop with aspectj (pre notification)

Posted by byp on Wed, 09 Feb 2022 23:06:08 +0100

CH06 aop aspectj: use aspectj framework to implement aop.
Using aop: the purpose is to add additional functions to some existing classes and methods. The premise is not to change the code of the original class.

Basic steps to implement aop using aspectj:

1. New maven project

2. Join dependency
  1) spring dependency
  2) aspectj dependency
  3) junit unit test

3. Create target class: interface and its implementation class.
  What we need to do is to add functionality to the methods in the class

4. Create section class: general class
  1) Add @ Aspect to the class
  2) Define a method in a class, which is the functional code to be executed
    Add the notification annotation in aspectj above the method, such as @ Before
    It is necessary to specify the pointcut expression execution()

5. Create spring configuration file: declare objects and hand them over to the container for unified management
  To declare objects, you can use annotations or xml configuration files < bean >
  1) Declare target object
  2) Declare facet class objects
  3) Declare the automatic proxy generator tag in the aspectj framework.
     Automatic proxy generator: used to complete the automatic creation of proxy objects.

6. Create a test class and get the target object (actually the proxy object) from the spring container.
  Through the agent execution method, the function of aop is enhanced.

 

1. Create a new module CH06 AOP AspectJ

2. Configure POM XML file, adding dependency

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.bjpowernode</groupId>
    <artifactId>ch06-aop-aspectj</artifactId>
    <version>1.0-SNAPSHOT</version>


    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <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>
</project>

3. Create target class: interface and its implementation class

package com.bjpowernode.ba01;

public interface SomeService {

    void doSome(String name,Integer age);
}
package com.bjpowernode.ba01;

//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()implement====");

    }
}

 4. Create facet class

1) Add @ Aspect to the class

2) Define the method in the class. The method is the function code to be executed. Add the notification annotation in aspectj on the method. For example, @ Before needs to specify the pointcut expression execution()

@Before

package com.bjpowernode.ba01;


import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

import java.util.Date;


/**
 *  @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 {
    /**
     * Define the method, which is to realize the section function.
     * Definition requirements of method:
     * 1.Public method public
     * 2.Method has no return value
     * 3.Method name customization
     * 4.Methods can have parameters or no parameters.
     *   If there are parameters, which are not user-defined, several parameter types can be used.
     */


    /**
     * @Before: Pre notification annotation
     *   Attribute: value, is the pointcut expression, which indicates the execution position of the function in 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.bjpowernode.ba01.SomeServiceImpl.doSome(String,Integer))")
    public void myBefore(){
        //Is the function to be performed
        System.out.println("Pre notification, aspect function: output the execution time before the target method:" + new Date());

    }
}

5. Create spring configuration file: declare the object and give it to the container for unified management. You can use annotation or xml configuration file < bean >

1) Declare target object

2) Declare facet class objects

3) Declare the automatic proxy generator tag in the aspectj framework. Automatic proxy generator: used to complete the automatic creation of proxy objects.

<?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: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/aop
       https://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--Give the object to spring Container, by spring Containers are created uniformly to manage objects-->
    <!--Declare target object-->
    <bean id="someService" class="com.bjpowernode.ba01.SomeServiceImpl" />

    <!--Declare facet class objects-->
    <bean id="myAspect" class="com.bjpowernode.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. Create as proxy object
        Therefore, the target object is the modified proxy object.

         aspectj-autoproxy:Will spring All target objects in the container generate proxy objects at one time.
    -->
    <aop:aspectj-autoproxy/>
</beans>

6. Create a test class and get the target object (actually the proxy object) from the spring container. Through the agent execution method, the function of aop is enhanced.

package com.bjpowernode;

import com.bjpowernode.ba01.SomeService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest01 {

    @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.doSome("lisi",20);
    }
}

7. The interface of the target class is jdk dynamic proxy

8. Multiple ways of writing pointcut expressions

(1) Omit access modifier

@Before(value = "execution(void com.bjpowernode.ba01.SomeServiceImpl.doSome(String,Integer))")
    public void myBefore(){
        //It is the function to be performed
        System.out.println("1===========Pre notification, aspect function: output the execution time before the target method:" + new Date());

    }

(2) * and Usage Used after the package name to indicate the path of the current package and its sub packages

@Before(value = "execution(void *..SomeServiceImpl.doSome(String,Integer))")
    public void myBefore(){
        //It is the function to be performed
        System.out.println("2===========Pre notification, aspect function: output the execution time before the target method:" + new Date());

    }

(3).. Used in method parameters to represent any number of parameters

 @Before(value = "execution(* *..SomeServiceImpl.doSome(..))")
    public void myBefore(){
        //It is the function to be performed
        System.out.println("3===========Pre notification, aspect function: output the execution time before the target method:" + new Date());

    }

(4) Use * to represent a series of methods

@Before(value = "execution(* *..SomeServiceImpl.do*(..))")
    public void myBefore(){
        //It is the function to be performed
        System.out.println("4===========Pre notification, aspect function: output the execution time before the target method:" + new Date());

    }

(5) Define two slice methods

@Before(value = "execution(* *..SomeServiceImpl.do*(..))")
    public void myBefore(){
        //It is the function to be performed
        System.out.println("4===========Pre notification, aspect function: output the execution time before the target method:" + new Date());

    }

    @Before(value = "execution(* *..SomeServiceImpl.do*(..))")
    public void myBefore2(){
        //It is the function to be performed
        System.out.println("4''===========Pre notification, aspect function: output the execution time before the target method:" + new Date());

    }

(6) The target class cannot be found

    @Before(value = "execution(void *..SomeServiceImpl.doSome(Integer))")
    public void myBefore(){
        //It is the function to be performed
        System.out.println("2===========Pre notification, aspect function: output the execution time before the target method:" + new Date());

    }

The target class here cannot be found, so the proxy class is not automatically generated for it