Principle and Configuration of AOP Face Oriented Programming in spring Bottom Layer

Summary

What is AOP

AOP is the abbreviation of Aspect Oriented Programming, meaning: Face-Oriented Programming

AOP was originally proposed by the organization of AOP Consortium, which specifies a set of specifications. spring introduces the idea of AOP into the framework, a technology for unified maintenance of programs through precompilation and dynamic agents during operation

Copyright attribution of the method of adding a log to a service in the citation https://pdai.tech All.

public class UserServiceImpl implements IUserService {
/**
 * find user list.
 *
 * @return user list
 */
@Override
public List<User> findUserList() {
    System.out.println("execute method:  findUserList");
    return Collections.singletonList(new User("pdai", 18));
}

/**
 * add user
 */
@Override
public void addUser() {
    System.out.println("execute method:  addUser");
    // do something
}
  }

To add logging to each method of a service, the traditional practice is to add logging to each method.
With the introduction of AOP, we decouple the logging functions into log facets. Cut the logging function horizontally into a separate module

  • In OOP object-oriented thinking, we abstract encapsulation of attributes (fields) and behaviors (methods) in the business process, the result of which is a class.
  • In the idea of AOP, we extract the facets from the business process. He is faced with a step of the process, has achieved the isolation effect of low coupling between the parts of the logical process, and the result of encapsulation is a facet (function).

There are essential differences in their goals

Terminology in AOP

  • Connection Point: An extension point that represents the ability to insert functionality into a business process, similar to a slot, where a connection point may be a class initialization. Method calls, field calls, exception handling, and so on. Spring only supports method execution connection points. ** Indicates where to operate**

  • Start Points: A set of connection points that represent a method in a specific class, while a start point is a set of connection points that have the same requirements that represent operations in those places.

  • Notification: Represents behavior performed at a connection point, and notification provides a means to extend existing behavior at the connection point selected at the entry point in AOP; Includes pre-advice, after-advice, around-advice, AOP in Spring through proxy mode, and notifications are woven into chains of interceptors around connection points through interceptor mode; Indicate what to do

  • Aspects: A collection module that cuts across concerns, such as the log component mentioned above, is a facet. Can be considered a combination of notifications, introductions and entry points;** Faces in AOP are like classes in OOP and are a specific module

  • Introducing: Introducing is the introduction of new interface enhancements on the basis of one interface.

  • Target object: The object that needs to be woven into a cross-cutting focus, that is, the object selected for the entry point and the object to be notified, which is also called the notified object; Because Spring AOP is implemented through the proxy mode, this object is always the proxy object, which is represented in the AOP as who does it;

  • Weave: Connect facets to other application types or objects and create a notified object. These can be done at compile time (for example, using the AspectJ compiler), class loading time, and runtime. Spring, like other pure Java AOP frameworks, finishes weaving at runtime. How is it represented in AOP?

  • **AOP proxy:**A specific implementation of weaving

Spring AOP and Aspectj

  • What is AspectJ first?

AspectJ is a Java-implemented AOP framework that enables AOP compilation of Java code (typically at compile time), allowing java code to have AspectJ's AOP functionality (requiring a special compiler, of course)

It can be said that AspectJ is the most mature and versatile language in the current AOP framework. Fortunately, AspectJ is fully compatible with and almost seamlessly associated with java programs, so it is very easy for engineers with a java programming base to get started and use.

  • Second, why do you need to clarify the relationship between Spring AOP and AspectJ?

Let's look at @Aspect and a few enhanced annotations. Why not the Spring package, but from aspectJ?

  • What is the relationship between Spring AOP and AspectJ?


  1. AspectJ is a stronger AOP framework and a practical AOP standard.

  1. Why doesn't Spring write a framework like AspectJ? Spring AOP is implemented using pure Java and does not require a specialized compilation process. An important principle of Spring AOP is non-invasiveness. The Spring team is fully capable of writing similar frameworks, but Spring AOP has never intended to compete with AspectJ by providing a comprehensive AOP solution. Spring's development team believes that proxy-based frameworks such as Spring AOP or mature frameworks such as AspectJ are valuable and should be complementary rather than competitive.

  2. The Spring group prefers the @AspectJ annotation style to the Spring XML configuration; So in Spring 2.0, the same annotations are used as AspectJ 5, and AspectJ is used for point-of-entry parsing and matching. However, AOP is still pure Spring AOP at runtime and does not depend on the compiler or weaver of AspectJ.

  1. Spring 2.5 support for AspectJ: In some environments, support for weaving when loading AspectJ has been added, while providing a new bean entry point.

The process by which AspectJ is applied to java code, called weaving, is simply understood as the process by which an aspect (facet) is applied to the target function (class).

For this process, it is generally divided into dynamic weaving and static weaving:

  • Dynamic weaving is the dynamic weaving of code to be enhanced into the target class during code execution, often through dynamic proxies.

  • Static weaving is mainly weaved during compilation. After compiling the aspect class into class byte code using AspectJ's acj compiler (similar to javac), it is weaved during the compilation of the java target class, that is, the aspect class is compiled before the target class is compiled.

AOP Configuration in Spring

XML Schema Configuration

Spring provides the use of an "aop" namespace to define a facet

  • Define target class
public class AopDemoServiceImpl {

    public void doMethod1() {
        System.out.println("AopDemoServiceImpl.doMethod1()");
    }

    public String doMethod2() {
        System.out.println("AopDemoServiceImpl.doMethod2()");
        return "hello world";
    }

    public String doMethod3() throws Exception {
        System.out.println("AopDemoServiceImpl.doMethod3()");
        throw new Exception("some exception");
    }
}
  • Define Face Class
public class LogAspect {

    /**
     * Surround notification.
     *
     * @param pjp pjp
     * @return obj
     * @throws Throwable exception
     */
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("-----------------------");
        System.out.println("Around Advice: Entry Method");
        Object o = pjp.proceed();
        System.out.println("Around Advice: Exit method");
        return o;
    }

    /**
     * Pre-notification.
     */
    public void doBefore() {
        System.out.println("Before advice");
    }

    /**
     * Post notification.
     *
     * @param result return val
     */
    public void doAfterReturning(String result) {
        System.out.println("after returning advise, Return value: " + result);
    }

    /**
     * Exception notification.
     *
     * @param e exception
     */
    public void doAfterThrowing(Exception e) {
        System.out.println("Exception Notification, abnormal: " + e.getMessage());
    }

    /**
     * Final Notification.
     */
    public void doAfter() {
        System.out.println("Final Notification");
    }

}
  • XML Configuration 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"
       xmlns:context="http://www.springframework.org/schema/context"
       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
 http://www.springframework.org/schema/context
 http://www.springframework.org/schema/context/spring-context.xsd
">

    <context:component-scan base-package="tech.pdai.springframework" />

    <aop:aspectj-autoproxy/>

    <!-- Target Class -->
    <bean id="demoService" class="tech.pdai.springframework.service.AopDemoServiceImpl">
        <!-- configure properties of bean here as normal -->
    </bean>

    <!-- section -->
    <bean id="logAspect" class="tech.pdai.springframework.aspect.LogAspect">
        <!-- configure properties of aspect here as normal -->
    </bean>

    <aop:config>
        <!-- Configure Faces -->
        <aop:aspect ref="logAspect">
            <!-- Configure entry points -->
            <aop:pointcut id="pointCutMethod" expression="execution(* tech.pdai.springframework.service.*.*(..))"/>
            <!-- Around Advice -->
            <aop:around method="doAround" pointcut-ref="pointCutMethod"/>
            <!-- Before advice -->
            <aop:before method="doBefore" pointcut-ref="pointCutMethod"/>
            <!-- Post-notification; returning Property: The name of the second parameter used to set the postnotification, of type Object -->
            <aop:after-returning method="doAfterReturning" pointcut-ref="pointCutMethod" returning="result"/>
            <!-- Exception notification: Enhancements will not be performed if there are no exceptions; throwing Property: Name, type used to set the second parameter of notification-->
            <aop:after-throwing method="doAfterThrowing" pointcut-ref="pointCutMethod" throwing="e"/>
            <!-- Final Notification -->
            <aop:after method="doAfter" pointcut-ref="pointCutMethod"/>
        </aop:aspect>
    </aop:config>

    <!-- more bean definitions for data access objects go here -->
</beans>
  • Test Class
public static void main(String[] args) {
    // create and configure beans
    ApplicationContext context = new ClassPathXmlApplicationContext("aspects.xml");

    // retrieve configured instance
    AopDemoServiceImpl service = context.getBean("demoService", AopDemoServiceImpl.class);

    // use configured instance
    service.doMethod1();
    service.doMethod2();
    try {
        service.doMethod3();
    } catch (Exception e) {
        // e.printStackTrace();
    }
}
  
  • Output Results
----------------------
Around Advice: Entry Method
 Before advice
AopDemoServiceImpl.doMethod1()
Around Advice: Exit method
 Final Notification
-----------------------
Around Advice: Entry Method
 Before advice
AopDemoServiceImpl.doMethod2()
Around Advice: Exit method
 Final Notification
 after returning advise, Return value: hello world
-----------------------
Around Advice: Entry Method
 Before advice
AopDemoServiceImpl.doMethod3()
Final Notification
 Exception Notification, abnormal: some exception


AspectJ Annotation Method

XML-based declarative AspectJ has some drawbacks that require a large amount of code information to be configured in the Spring configuration file. To solve this problem, Spring uses the @AspectJ framework to provide a set of annotations for the implementation of AOP.

Note Nameexplain
@AspectUsed to define a facet.
@pointcutUsed to define an entry point expression. You also need to define a method signature with a name and any parameters to represent the entry point name, which is a common method with a void return value and an empty method body.
@BeforeUsed to define pre-notifications, equivalent to BeforeAdvice. In use, you usually need to specify a value attribute value that specifies an entry point expression (either an existing entry point or a direct definition of the entry point expression).
@AfterReturningUsed to define post-notifications, equivalent to AfterReturningAdvice. You can specify pointcut / value and returning attributes when using, where pointcut / value are used to specify the entry point expression in the same way.
@AroundUsed to define surround notifications, equivalent to MethodInterceptor. When used, you need to specify a value property that specifies the entry point where the notification is implanted.
@After-ThrowingUsed to define exception notifications to handle unhandled exceptions in a handler, equivalent to ThrowAdvice. You can specify pointcut / value and throwing attributes when using. The pointcut/value is used to specify the entry point expression, and the throwing attribute value is used to specify - a parameter name to indicate that a parameter with the same name can be defined in the Advice method, which can be used to access exceptions thrown by the target method.
@AfterUsed to define the final notification, which executes regardless of the exception. When using, you need to specify a value property that specifies the entry point where the notification is implanted.
@DeclareParentsUsed to define introductory notifications, equivalent to IntroductionInterceptor (not required).

Define the facets using annotations and weave them into the method

ackage tech.pdai.springframework.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;


@EnableAspectJAutoProxy
@Component
@Aspect
public class LogAspect {

    /**
     * define point cut.
     */
    @Pointcut("execution(* tech.pdai.springframework.service.*.*(..))")
    private void pointCutMethod() {
    }


    /**
     * Surround notification.
     *
     * @param pjp pjp
     * @return obj
     * @throws Throwable exception
     */
    @Around("pointCutMethod()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("-----------------------");
        System.out.println("Around Advice: Entry Method");
        Object o = pjp.proceed();
        System.out.println("Around Advice: Exit method");
        return o;
    }

    /**
     * Pre-notification.
     */
    @Before("pointCutMethod()")
    public void doBefore() {
        System.out.println("Before advice");
    }


    /**
     * Post notification.
     *
     * @param result return val
     */
    @AfterReturning(pointcut = "pointCutMethod()", returning = "result")
    public void doAfterReturning(String result) {
        System.out.println("after returning advise, Return value: " + result);
    }

    /**
     * Exception notification.
     *
     * @param e exception
     */
    @AfterThrowing(pointcut = "pointCutMethod()", throwing = "e")
    public void doAfterThrowing(Exception e) {
        System.out.println("Exception Notification, abnormal: " + e.getMessage());
    }

    /**
     * Final Notification.
     */
    @After("pointCutMethod()")
    public void doAfter() {
        System.out.println("Final Notification");
    }

}

Declaration rules for entry points

Spring AOP users may often use the execution entry point indicator.

Copyright Ownership https://pdai.tech all.
Links: https://www.pdai.tech/md/spring/spring-x-framework-aop.html

// Execution of any public method:
execution(public * *(..))

// Execution of any method whose name begins with "set":
execution(* set*(..))

// Execution of any method defined by the AccountService interface:
execution(* com.xyz.service.AccountService.*(..))

// Execution of any method defined in the service package:
execution(* com.xyz.service.*.*(..))

// Execution of any method defined in a service package or its subpackages:
execution(* com.xyz.service..*.*(..))

// Any connection point in the service package (only method execution in Spring AOP):
within(com.xyz.service.*)

// Any join point in the service package or its subpackages (only method execution in Spring AOP):
within(com.xyz.service..*)

// Any connection point of the proxy object that implements the AccountService interface (only method execution in Spring AOP):
this(com.xyz.service.AccountService)// 'this'is more common in binding forms

// Any connection point for the target object that implements the AccountService interface (only method execution in Spring AOP):
target(com.xyz.service.AccountService) // 'target'is more common in binding forms

// Any parameter that accepts only one parameter and is passed in at runtime is the connection point of the Serializable interface (only method execution in Spring AOP)
args(java.io.Serializable) // 'args'is more commonly used in binding forms; Note that the starting point given in the example is different from execution(* *(java.io.Serializable)): the args version matches only when the incoming parameter is Serializable at dynamic runtime, and the execution version matches when it declares only one parameter of type Serializable in the method signature.

// Any connection point with a @Transactional annotation in the target object (only method execution in Spring AOP)
@target(org.springframework.transaction.annotation.Transactional)// '@target'is more common in binding forms

// Any type declared by a target object has a connection point for the @Transactional annotation (only method execution in Spring AOP):
@within(org.springframework.transaction.annotation.Transactional) // '@within'is more common in binding forms

// Any method executed has a connection point for the @Transactional annotation (only method execution in Spring AOP)
@annotation(org.springframework.transaction.annotation.Transactional) // '@annotation'is more common in binding forms

// Any parameter that accepts only one parameter and the type of parameter passed in at runtime has a connection point with the @Classified annotation (only method execution in Spring AOP)
@args(com.xyz.security.Classified) // '@args'is more common in binding forms

// Any connection point on a Spring bean named'tradeService'(only method execution in Spring AOP)
bean(tradeService)

// Any connection point above the Spring bean whose name matches the wildcard expression'*Service'(method execution only in Spring AOP)
bean(*Service)

Combination of entry points

&&: Require connection points to match two entry point expressions at the same time
||: Require connection points to match any entry point expression
!:: Requires that connection points do not match the specified entry point expression

Key differences between Spring AOP and AspectJ?

AspectJ can do things Spring AOP can't do, it's the complete solution for AOP programming
Spring AOP is committed to resolving the most common AOP in enterprise development.

[

](https://www.pdai.tech/md/spring/spring-x-framework-aop.html)

Spring AOPAspectJ
Implemented in pure JavaExtended implementation using Java programming language
No separate compilation process is requiredAspectJ compiler (ajc) is required unless LTW is set
Only runtime weaving is availableRuntime weaving is not available. Supports compile-time, post-compile, and load-time weaving
Poor functionality - only method level weaving is supportedMore powerful - can braid fields, methods, constructors, static initializers, final classes/methods, etc.
Can only be implemented on bean s managed by Spring containersCan be implemented on all domain objects
Only method execution entry points are supportedSupports all entry points
Proxies are created by the target object, and facets are applied to these proxiesBefore executing the application (at runtime), all aspects are directly woven into the code
Much slower than AspectJBetter performance
Easy to learn and applyMore complex than Spring AOP

Keywords: Java Spring Back-end AOP source code

Added by ed01 on Sat, 05 Feb 2022 19:11:12 +0200