Detailed configuration and usage examples of Spring AOP

Posted by maheshbaba on Fri, 18 Feb 2022 10:35:34 +0100

What is AOP

AOP (Aspect Oriented Programming) means: aspect oriented programming, which realizes the unified maintenance of program functions through precompiled mode and runtime dynamic agent. AOP is a continuation of OOP. It is not only a hot spot in software development, but also an important content in Spring framework. It is a derivative paradigm of functional programming. AOP can isolate all parts of business logic, so as to reduce the coupling between all parts of business logic, improve the reusability of programs, and improve the efficiency of development.

The role of AOP in Spring

Provide declarative transactions: allow users to customize aspects

  • Crosscutting concerns: methods or functions that span multiple modules of an application. That is, the part that has nothing to do with our business logic, but we need to focus on is crosscutting concerns. Such as log, security, cache, transaction and so on
  • Aspect: a special object whose crosscutting concerns are modularized. That is, it is a class.
  • Advice: work that must be completed in all aspects. That is, it is a method in a class.
  • Target: the notified object.
  • Proxy: an object created after notification is applied to the target object.
  • Pointcut: the definition of the "place" where the aspect notification is executed.
  • Jointpoint: the execution point that matches the pointcut.

    In spring Aop, crosscutting logic is defined through Advice. Spring supports five types of Advice (that is, Aop adds new functions without changing the original code)

Using Spring to implement AOP

To use AOP weaving, you need to import dependent packages

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.6</version>
</dependency>

Method 1: use Spring's API interface (mainly API interface implementation)

  • service and serviceImpl
public interface UserService {
    public void add();
    public void delete();
    public void update();
    public void select();
}
public class UserServiceImpl implements UserService{
    public void add() {
        System.out.println("Added a user");
    }

    public void delete() {
        System.out.println("A user was deleted");
    }

    public void update() {
        System.out.println("Updated a user");
    }

    public void select() {
        System.out.println("Queried a user");
    }
}
  • Log classes (before and after)
public class BeforeLog implements MethodBeforeAdvice {
    //Method: the method of the target object to execute
    //object: parameter
    //Target: target object
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println(target.getClass().getName() + "of" + method.getName() + "Executed");
    }
}
public class AfterLog implements AfterReturningAdvice {
    //returnValue: return value
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("Yes" + method.getName() + "Method, the return result is" + returnValue);
    }
}
  • configuration file
    Note the constraints that need to be imported into aop
<?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.zzy.service.UserServiceImpl"/>
    <bean id="beforelog" class="com.zzy.log.BeforeLog"/>
    <bean id="afterLog" class="com.zzy.log.AfterLog"/>

    <!--Use native api Interface-->
    <!--to configure aop,Import required aop Constraints of-->
    <aop:config>
        <!--Entry point, expression expression: execution([Method access modifier] Method return value package name.Class name.Method name(Method parameters))-->
        <aop:pointcut id="pointcut" expression="execution(* com.zzy.service.UserServiceImpl.*(..))"/>

        <!--Execute surround increase-->
        <aop:advisor advice-ref="beforelog" pointcut-ref="pointcut"/>
        <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
    </aop:config>
</beans>
  • Test class
public class Test {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //Like dynamic proxies, interfaces are used
        UserService userService = (UserService) context.getBean("userService");
        userService.add();
    }
}
  • test result

Method 2: user defined classes implement AOP (mainly section definition)

  • Custom facet class
public class DiyPointCut {
    public void before(){
        System.out.println("Before method execution");
    }
    public void after(){
        System.out.println("After method execution");
    }
}
  • configuration file
<?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.zzy.service.UserServiceImpl"/>

    <!--Custom class-->
    <bean id="diy" class="com.zzy.diy.DiyPointCut"/>
    
    <aop:config>
        <!--Custom section, ref Class to import-->
        <aop:aspect ref="diy">
            <!--breakthrough point-->
            <aop:pointcut id="point" expression="execution(* com.zzy.service.UserServiceImpl.*(..))"/>
            <!--notice-->
            <aop:before method="before" pointcut-ref="point"/>
            <aop:after method="after" pointcut-ref="point"/>
        </aop:aspect>
    </aop:config>
</beans>
  • test result

Method 3: implement with annotation

  • Annotation facet class
//Dimensions are tangent
@Aspect
public class AnnotationPointCut {

    @Before("execution(* com.zzy.service.UserServiceImpl.*(..))")
    public void before(){
        System.out.println("Before method execution");
    }

    @After("execution(* com.zzy.service.UserServiceImpl.*(..))")
    public void after(){
        System.out.println("After method execution");
    }
	
    //aop surround
    @Around("execution(* com.zzy.service.UserServiceImpl.*(..))")
    public void around(ProceedingJoinPoint jp) throws Throwable {
        System.out.println("Surround front");
        //Get method signature
        System.out.println(jp.getSignature());
        //Execution method
        jp.proceed();
        System.out.println("After surround");
    }
}
  • configuration file
<?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.zzy.service.UserServiceImpl"/>

    <!--Write custom cut bean-->
    <bean id="annotationPointCut" class="com.zzy.diy.AnnotationPointCut"/>
    
    <!--Enable annotation support
    Default use jdk Dynamic agent( proxy-target-class="false") use cglib Dynamic agent( proxy-target-class="true")-->
    <aop:aspectj-autoproxy/>
</beans>
  • test result

Topics: Java Spring Back-end