Spring AOP (aspect-oriented programming) and AspectJ framework to achieve AOP (annotation)

What is AOP

(1) Aspect-oriented programming (aspect), the use of AOP can isolate each part of the business logic, so that the coupling degree between the parts of the business logic is reduced, the reusability of the program is improved, and the efficiency of development is improved.
(2) Popular description: Add new functions to the main function without modifying the source code
(3) Use the example of login to illustrate AOP

The role of AOP

Provide declarative transactions: allow users to customize aspects
The following nouns need to be understood:
1. Connection point (JointPoint)
Which methods in the class can be enhanced, these methods are called connection points
2. Entry point (PointCut)
The methods that are actually enhanced are called pointcuts
3. Notification (enhancement) (Advice)
(1) The logical part that is actually enhanced is called notification (enhancement)
(2) There are various types of notifications:
Pre-advice: execute before the method
Post-advice: execute after the method
Surround advice: execute both before and after the method
Exception notification: Execute only when an exception occurs in the method
Final notification: After the method ends, it will be executed no matter what, similar to finally
Notification can be understood as execution, adding code
4. Cross-cutting concerns: methods or functions that span multiple modules of the application. That is, the part that has nothing to do with our business logic, but we need to pay attention to, is the cross-cutting concern. Such as logs, security, cache, transactions, etc...
5. Aspect: A special object whose cross-cutting concerns are modularized. That is, it is a class.
6. Target: The object whose code is added.
7. Proxy (Proxy): The object created after applying the notification to the target object.

Pointcut expression:

execution (public * com.service.impl....(...))
execution (permission modifier, return value type, class full path, method name, parameter list)
1.execution: indicator, execution is the most commonly used indicator, used to match the connection point of method execution.
2.public: access modifier, this parameter is optional.
3. The first * number: the return value type, the number indicates all types, that is, wildcards.
4. Package name: The name of the package to be intercepted. The two dots behind represent the current package and all subpackages of the current package, that is, the com.service.impl package in the example and all classes under the package’s descendants.
5. The second number: the class name, * means all classes.
*(…): method name, * indicates all methods, the parameters in the brackets indicate the parameters of the method, two dots indicate any parameters, optional.

Implementation of spring transactions

first step:

<!--To configure declarative transactions, use spring Inside, it will be injected through the constructor, and a data source needs to be injected
<bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">-->
    <bean id="transaction" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <constructor-arg ref="datasource"/>
    </bean>

Step two:

<!--combine Aop Weaving in business-->
<!--    Notifications for configuration transactions-->
    <tx:advice id="txAdvice" transaction-manager="transaction">
<!--        Prepare to configure transactions for those methods-->
<!--        Configure the propagation characteristics of transactions: new propagation There are seven types, generally only one required,Baidu understands-->
        <tx:attributes>
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>

third step:

<!--    Configure transaction cut-in
aop:pointcut: Target
aop:advisor advice-ref: method to inject-->
    <aop:config>
        <aop:pointcut id="txPointCut" expression="execution(* com.mybatis.*.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
    </aop:config>

Step Four: Test

    @Override
    public List<Emp> selectAllEmp() {
        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
        List<Emp> list = mapper.selectAllEmp();
        try {
            Emp emp = new Emp(null, "Linghu Chong", 20, "male", "123@qq.com");
            List<Emp> list1 = Arrays.asList(emp);
            this.addMoreByList(list1);
            String[] eids={"25","26","27"};
//            int a=1/0;
            this.deleteMoreByArray(eids);
        } catch (Exception e) {
            e.printStackTrace();
            sqlSession.rollback();
        }
        return list;
    }

Other examples:

public class DiyPointCut {
    public void before(){
        System.out.println("======pre-method execution=========");
    }
    public void after(){
        System.out.println("======post method execution=========");
    }
}

public class UserServiceImpl implements UserService{
    @Override
    public void add() {
        System.out.println("added a user");
    }

    @Override
    public void delete() {
        System.out.println("deleted a user");
    }

    @Override
    public void update() {
        System.out.println("updated a user");
    }

    @Override
    public void query() {
        System.out.println("queried a user");
    }
}
<?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 
       http://www.springframework.org/schema/aop/spring-aop.xsd">
    
    <bean id="userService" class="com.tzm.Demo1.UserServiceImpl"></bean>
    <bean id="log" class="com.tzm.Demo1.log.Log"/>
    <bean id="afterLog" class="com.tzm.Demo1.log.AfterLog"/>
    <!--use native spring API accomplish-->
    <aop:config>
        <!--    entry point-->
        <aop:pointcut id="pointcut2" expression="execution(* com.tzm.Demo1.UserServiceImpl.*(..))"/>
        <!--    Perform Surround Enhancement-->
        <aop:advisor advice-ref="log" pointcut-ref="pointcut2"/>
        <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut2"/>
    </aop:config>
    
    <!--    Implemented with a custom class-->
    <bean id="diyPointcut" class="com.tzm.Demo1.diy.DiyPointCut"></bean>
    <aop:config>
        <aop:aspect ref="diyPointcut">
            <aop:pointcut id="point" expression="execution(* com.tzm.Demo1.UserServiceImpl.*(..))"/>
            <aop:before method="before" pointcut-ref="point"/>
            <aop:after method="after" pointcut-ref="point"/>
        </aop:aspect>
    </aop:config>
</beans>

AspectJ framework implements AOP (annotation)

@Before: pre-enhancement
@AfterReturning: post-return enhancement
@Around: surround enhancement
@AfterThrowing: exception enhancement
@After: final enhancement
@Pointcut: Define pointcut

Steps for usage

1.pom.xml

<!--import aspectJ rely-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>5.3.20</version>
</dependency>

2. Write the enhanced class: UserDao

/**
 * Proxied object
 */
public class UserDao {
  public void add() {
    // TODO Auto-generated method stub
    System.out.println("add customer");
  }
  public void delete() {
    // TODO Auto-generated method stub
    System.out.println("delete customer");
    int i=1/0;
  }
  public String find() {
    // TODO Auto-generated method stub
    System.out.println("Query customers");
    return "fanhuizhi";
  }
  public void update() {
    // TODO Auto-generated method stub
    System.out.println("modify customer");
  }
}
3.use AspectJ Annotation form:

```java
/**
 * NOP Sectional class: the combination of point cutting and enhancement
 */
@Aspect
public class MyAspect {
  @Before(value = "execution(* com.UserDao.add(..))")//Write expressions here, write which classes need to be added
  public void before(JoinPoint joinpoint) {
    System.out.println("Pre-enhancement..."+joinpoint);
  }

  @AfterReturning(value = "execution(* com.UserDao.find(..))",returning="returnVal")//Write expressions here, write which classes need to be added
  public void afterReturning(Object returnVal){
    System.out.println("Post Enhancement..."+"method return value"+returnVal);
  }

  @Around(value = "execution(* com.UserDao.delete(..))")//Write expressions here, write which classes need to be added
  public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
    System.out.println("pre-surround enhancement...");
    Object obj = proceedingJoinPoint.proceed();
    System.out.println("Surround Enhancement...");
    return obj;
  }

  @AfterThrowing(value = "execution(* com.UserDao.delete(..))",throwing="ex")//Write expressions here, write which classes need to be added
  public void afterThrowing(Throwable ex) throws Throwable{
    System.out.println("No more exceptions..."+ex.getMessage());
  }

  //@After(value = "execution(* com.UserDao.delete(..))")//Write expressions here, write which classes need to be added
  @After("MyAspect.MyPointCut()")//class name. method name
  public void after(){
    System.out.println("final notice");//No matter if there is any abnormality, it will be notified
  }

  //The definition of pointcut is only to define a general expression
  @Pointcut(value = "execution(* com.UserDao.delete(..))")
  private void MyPointCut(){
  }
  
}

4. Create applicationContext.xml

<!--introduce aop constraints:-->
xmlns:aop="http://www.springframework.org/schema/aop"
<!-- The bottom layer of automatic proxy generation is AnnotationAwareAspectJautoProxyCreator -->
<aop:aspectj-autoproxy/>

<bean id="userDao" class="com.UserDao"/>

<bean id="MyAspect" class="com.MyAspect"/>

5. Test run

Tags: Java Spring Back-end

Posted by koen on Sun, 20 Nov 2022 00:31:39 +0300