Learn spring 5 architecture from scratch -- explain AOP in detail

Keywords: Java Spring AOP ioc mvc

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 the continuation of OOP, a hot spot in software development, an important content in Spring framework, and a derivative paradigm of functional programming. 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.


The role of AOP in Spring

Provide declarative transactions; Allows you to customize the cut plane

  • 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 logging, security, caching, transactions, etc

  • 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.

  • Join point: 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

Implementing AOP through Spring

To use AOP weaving, you need to import a dependency package

<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.7</version>
</dependency>

Spring's Aop combines public business (log, security, etc.) with domain business. When executing domain business, it will add public business to realize the reuse of public business. Domain business is more pure. Programs focus on domain business. Its essence is dynamic agent

Implemented through Spring API

Interface class:

package com.pag.service;

public interface UserService {
    public void add();
    public void delete();
    public void update();
    public void query();

}

Implementation class:

package com.pag.service;

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

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

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

    @Override
    public void query() {
        System.out.println("Query user");
    }
}

Enhancement class:
Pre enhancement:

package com.pag.log;

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

public class Log implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println(target.getClass()+"of"+method.getName()+"Method was executed");
    }
}

Post enhancement:

package com.pag.log;

import org.springframework.aop.AfterReturningAdvice;

import java.lang.reflect.Method;

public class AfterLog implements AfterReturningAdvice {
    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("Yes" + target.getClass().getName()
                +"of"+method.getName()+"method,"
                +"Return value:"+returnValue);
    }
}

spring configuration file:

    <!--register bean-->
    <bean id="userService" class="com.pag.service.UserServiceImpl"/>
    <bean id="log" class="com.pag.log.Log"/>
    <bean id="afterLog" class="com.pag.log.AfterLog"/>
    <!--aop Configuration of-->
    <aop:config>
        <!--breakthrough point  expression:The expression matches the method to execute-->
        <aop:pointcut id="pointcut" expression="execution(* com.pag.service.UserServiceImpl.*(..))"/>
        <!--Perform wrap; advice-ref Execution method . pointcut-ref breakthrough point-->
        <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
        <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
    </aop:config>

Test:

    @Test
    public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService = (UserService) context.getBean("userService");
        userService.query();
    }

Implemented through custom classes

Cut in class:

package com.pag.config;

public class DiyPointcut {
    public void before(){
        System.out.println("---------Before method execution---------");
    }
    public void after(){
        System.out.println("---------After method execution---------");
    }
}

spring configuration file:

    <!--The second way is to customize the implementation-->
    <!--register bean-->
    <bean id="diy" class="com.pag.config.DiyPointcut"/>
    <!--aop Configuration of-->
    <aop:config>
        <!--The second way: use AOP Label Implementation of-->
        <aop:aspect ref="diy">
            <aop:pointcut id="diyPonitcut" expression="execution(* com.pag.service.UserServiceImpl.*(..))"/>
            <aop:before pointcut-ref="diyPonitcut" method="before"/>
            <aop:after pointcut-ref="diyPonitcut" method="after"/>
        </aop:aspect>
    </aop:config>

Test:

    @Test
    public void test1(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService = (UserService) context.getBean("userService");
        userService.add();
    }

Implemented through annotations

Enhanced classes for annotation entities:

package com.pag.config;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class AnnotationPointcut {
    @Before("execution(* com.pag.service.UserServiceImpl.*(..))")
    public void before(){
        System.out.println("---------Before method execution---------");
    }
    @After("execution(* com.pag.service.UserServiceImpl.*(..))")
    public void after(){
        System.out.println("---------After method execution---------");
    }
    @Around("execution(* com.pag.service.UserServiceImpl.*(..))")
    public void around(ProceedingJoinPoint jp) throws Throwable {
        System.out.println("Surround front");
        System.out.println("autograph:"+jp.getSignature());
        //Execute target method
        Object proceed = jp.proceed();
        System.out.println("After surround");
        System.out.println(proceed);
    }
}

spring configuration file:

    <!--The third way:Annotation implementation-->
    <bean id="annotationPointcut" class="com.pag.config.AnnotationPointcut"/>
    <aop:aspectj-autoproxy/>

aop:aspectj-autoproxy:

  • Through the < aop: aspectJ AutoProxy / > declaration of the aop namespace, automatically create a proxy for those bean s configured with the @ aspectJ aspect in the spring container and weave the aspect in. Of course, spring still uses AnnotationAwareAspectJAutoProxyCreator internally to create automatic proxy, but the specific implementation details have been hidden by < aop: aspectJ AutoProxy / >
  • < AOP: AspectJ AutoProxy / > has a proxy target class attribute, which is false by default, indicating that jdk dynamic proxy is used for weaving enhancement. When it is configured as < AOP: AspectJ AutoProxy poxy target class = "true" / /, it indicates that CGLib dynamic proxy technology is used for weaving enhancement. However, even if proxy target class is set to false, if the target class does not declare an interface, spring will automatically use CGLib dynamic proxy.

Posted by shamil on Fri, 01 Oct 2021 18:02:25 -0700