Talking about AOP, AspectJ and Spring AOP

Keywords: Java Spring JDK Programming

introduction

AOP (Aspect Orient Programming), as a supplement to object-oriented programming, is widely used to handle some cross-cutting system-level services, such as log collection, transaction management, security checking, caching, object pool management, etc. The key of AOP implementation lies in the AOP proxy created automatically by AOP framework. AOP proxy can be divided into static proxy and dynamic proxy. Among them, static proxy refers to compiling commands provided by AOP framework, so that AOP proxy class can be generated at compilation stage, which is also called compile-time enhancement; while dynamic proxy relies on JDK dynamic proxy and CGLIB in memory at runtime. The "temporary" generation of AOP dynamic proxy classes is also known as runtime enhancement.

Aspect-oriented programming (AOP) is a programming paradigm designed to improve modularity by allowing the separation of cross-cutting concerns. AOP provides aspects to modularize cross-object concerns. Although many AOP frameworks are available now, there are only two popular frameworks to distinguish here: Spring AOP and AspectJ.

Key concepts

Aspect

Aspect is translated aspect or aspect, which is equivalent to the class in OOP. It encapsulates the function used for horizontal insertion system. For example, log, transaction, security verification, etc.

JoinPoint

JoinPoint is an important key concept in AOP. JoinPoint can be seen as an execution point when the program is running. For example, to execute the function System.out.println("Hello"), println() is a join point; to assign a variable is also a join point; and the most commonly used for loop is also a join point.

In theory, many parts of a program can be considered JoinPoint, but in AspectJ, only the following execution points are considered JoinPoint:

<center>Table 1 Types of JoinPoint </center>

JoinPoint Explain Example
method call function call For example, call Logger.info(), which is a JoinPoint
method execution Function execution For example, inside the execution of Logger.info() is a JoinPoint. Notice the difference between it and method call. Method call is where a function is called. Execution is the internal execution of a function.
constructor call constructor call Similar to method call
constructor execution Constructor Execution Similar to method execution
field get Get a variable For example, read User.name members
field set Setting a variable For example, set User.name members
pre-initialization Object does some work in constructors.
initialization Object works in constructors
static initialization Class initialization For example, class static {}
handler exception handling For example, in try catch(xxx), it corresponds to execution in catch
advice execution This is AspectJ's content

The types of JoinPoint recognized by AspectJ are listed here. In fact, the connection point is where you want to insert new code into a program, whether in a construction method, before a method call, or before a method call. This place is JoinPoint. Of course, not everywhere can insert it for you. Only where you can insert it, it is called JoinPoint.

PointCut

PointCut is popularly translated as entry point. A program will have multiple Join Points. Even if the same function is divided into call and execution type Join Points, but not all Join Points are of concern to us. Pointcut is a method that enables developers to choose the Join Point they need. PointCut is divided into call, execution, target, this, within and other keywords. Compared with joinPoint, pointcut is a tangent point.

Advice

Advice translates into advisor, which is how we insert code, which is equivalent to the method in OOP, including Before, After and Around.

  • Before

The pre-notification is used to insert the aspect code into the method, that is, before the method is executed, the code in the pre-notification is executed first. The class that contains the pre-notification code is the aspect.

  • After

The code for the post-notification calls after calling the intercepted method.

  • Around

The ability to surround notifications is strongest. The notification code can be executed before method invocation, and the target method can be decided whether or not to invoke. That is to say, it can control the execution of the intercepted method and the return value of the intercepted method.

Target

Target refers to the target class or interface that needs to be cut into.

Proxy

Proxy is a proxy, and AOP works by accessing the target object through the proxy object. Actually, AOP is implemented through dynamic proxy, which can not be separated from proxy mode, so there must be a proxy object.

Weaving

Weaving is weaving. The process of inserting section code into the target object is called weaving.

AspectJ

Introduction to AspectJ

AspectJ is an aspect-oriented framework that defines some of AOP's syntax and has a special bytecode generator to generate class files that conform to the java specification.

AspectJ's notification types include not only the three notifications we've known before: pre-notification, post-notification, surround notification, exception notification in Aspect, and a final notification that the code for the final notification will be executed regardless of whether the program is executed properly or not.

AspectJ provides its own expression language, tangent expression, which identifies which methods the tangent weaves into which classes. Just configure the implementation of the aspect and write the pointcut expression. No additional xml configuration is required.

Tangent expression grammar:

execution(
    modifiers-pattern? //Access privilege matching, such as public, protected
    ret-type-pattern //Return value type matching
    declaring-type-pattern? //Fully qualified class names
    name-pattern(param-pattern) //Method name (parameter name)
    throws-pattern? //Thrown exception type
)

Be careful:
1. Spaces are separated in the middle. Questionmark attributes can be omitted.
2. Specific symbols in expressions indicate:

  • A: * Represents 0 to more than one arbitrary character and is usually used for certain classes and methods under a package.
  • b:... In the method parameter, representing any parameter, and after the package name, representing the current package and all its subpackage paths.
  • c: +After the class name, represents the current class and its subclasses, after the interface, represents the current interface and its implementation class.

Table 2 method expression </center>

Expression Meaning
java.lang.String Matching String Types
java.*.String Match any String type under the "first-level subpackage" under the Java package, such as matching java.lang.String, but not java.lang.ss.String
java..* Match any type of java package and any subpackage, such as java.lang.String, java.lang.annotation.Annotation
java.lang.*ing Match any type ending in ing under the java.lang package
java.lang.Number+ Match any Number's self-type under the java.lang package, such as matching java.lang.Integer, and also matching java.math.BigInteger

< center > Table 3 parameter expression </center >

parameter Meaning
() The representation has no parameters
(..) A Method for Representing Matching Accepting Arbitrary Parameters
(..,java.lang.String) Represents that matching accepts the end of a parameter of type java.lang.String and that the method with any parameter can be accepted in front of it
(java.lang.String,..) A method that indicates that matching accepts a parameter of type java.lang.String to begin with and any parameter to follow.
(*,java.lang.String) Represents the end of a match that accepts a parameter of type java.lang.String and the method that accepts an arbitrary parameter of type ahead of it

Take a chestnut: execution(public * com.zhoujunwen.service. *. * (.)), which represents any method of any class of public access rights under the com.zhoujunwen.service package.

Installation of AspectJ and Common Commands

AspectJ Download Address( http://www.eclipse.org/aspect... Select the appropriate version to download on the download page. The latest stable version is 1.9.1. After downloading, double jar packages are installed. The installation interface is as follows:

The following structure can be seen with the tree command for the installation directory (excluding the doc directory):

├── LICENSE-AspectJ.html
├── README-AspectJ.html
├── bin
│   ├── aj
│   ├── aj5
│   ├── ajbrowser
│   ├── ajc
│   └── ajdoc
└── lib
    ├── aspectjrt.jar
    ├── aspectjtools.jar
    ├── aspectjweaver.jar
    └── org.aspectj.matcher.jar

42 directories, 440 files
  • bin: Store aj, aj5, ajc, ajdoc, ajbrowser and other commands, of which AJC command is the most commonly used, and its role is similar to javac.
  • doc: Documents such as AspectJ instructions, reference manuals, API documents are stored.
  • lib: The four JAR files under this path are the core class libraries of AspectJ.

Note that after installation, you need to configure aspectjrt.jar to CLASSPATH and bin directory to PATH. The following is an example of MacOs configuration:

JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home
CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:/Users/yourname/Documents/software/aspectj1.9.1/lib/aspectjrt.jar

M2_HOME=/Users/yourname/Documents/software/apache-maven-3.5.0
PATH=$JAVA_HOME/bin:$M2_HOME/bin:/usr/local/bin:/Users/yourname/Documents/software/aspectj1.9.1/bin:$PATH

Note: where / Users/yourname/Documents/software/aspectj1.9.1/lib/aspectjrt.jar replaces lib of the path where you installed AspectJ, and / Users/yourname/Documents/software/aspectj1.9.1/bin replaces bin directory where you installed AspectJ.

demo of AspectJ

Verify AspectJ's slice function, write a simple AspectJ demo, implement method log burying point, and enhance after the method.

Business code (AuthorizeService.java):

package com.zhoujunwen.aop;

/**
* It is not necessary to deal with business logic too seriously. You can understand it.
* @author zhoujunwen
* @version 1.0.0
*/
public class AuthorizeService {
    private static final String USERNAME = "zhoujunwen";
    private static final String PASSWORD = "123456";
    public void login(String username, String password) {
        if (username == null || username.length() == 0) {
            System.out.print("User name cannot be empty");
            return;
        }
        if (password == null || password.length() == 0) {
            System.out.print("User name cannot be empty");
            return;
        }
        if (!USERNAME.equals(username) || !PASSWORD.equals(password)) {
            System.out.print("Incorrect username or password");
            return;
        }
        System.out.print("Successful login");
    }

    public static void main(String[] args) {
        AuthorizeService as = new AuthorizeService();
        as.login("zhoujunwen", "123456");
    }
}

LogAspect. java:

package com.zhoujunwen.aop;

public aspect LogAspect {
    pointcut logPointcut():execution(void AuthorizeService.login(..));
    after():logPointcut(){
         System.out.println("****Processing logs****"); 
    }
} 

Place the above two file files in the same directory, and execute the command of acj compilation and weaving in the current directory:

ajc -d . AuthorizeService.java LogAspect.java

If you configure all OK, no exceptions or errors will occur. In the current directory, two bytecode files, com/zhoujunwen/aop/AuthorizeService.class and com/zhoujunwen/aop/LogAspect.class, will be generated. The directory structure will be viewed by executing tree (tree command written by myself similar to Linux tree command):

zhoujunwendeMacBook-Air:aop zhoujunwen$ tree
.
├── AuthorizeService.java
├── LogAspect.java
└── com
    └── zhoujunwen
        └── aop
            ├── AuthorizeService.class
            └── LogAspect.class

3 directories, 4 files

Finally, execute the java execution command:

java com/zhoujunwen/aop/AuthorizeService

Output log content:
Logon successfully processed logs

ajc can be understood as javac commands, which are used to compile Java programs. The difference is that ajc commands recognize AspectJ's syntax; we can treat ajc as an enhanced version of javac commands. The AuthorizeService.class file after the ajc command is executed is not compiled from the original AuthorizeService.java file. The AuthorizeService.class adds the content of print logs - which indicates that AspectJ compiles automatically at compilation time and gets a new class, which enhances the functions of the original AuthorizeService.java class, so AspectJ is usually called compilation. Time-enhanced AOP framework.

To verify the above conclusion, we decompile the AuthorizeService.class file with the javap command. Javap is a Java class file decomposer, which can decompile (that is, decompile the files compiled by javac) or view the bytecode generated by the java compiler. Used to decompose class files.

javap -p -c com/zhoujunwen/aop/AuthorizeService.class

The output is as follows. Where the code of the login method is 0, 3 and 91, 94, invokestatic and com/zhoujunwen/aop/LogAspect are found, which shows that the above conclusion is correct.

Compiled from "AuthorizeService.java"
public class com.zhoujunwen.aop.AuthorizeService {
  private static final java.lang.String USERNAME;

  private static final java.lang.String PASSWORD;

  public com.zhoujunwen.aop.AuthorizeService();
    Code:
       0: aload_0
       1: invokespecial #16                 // Method java/lang/Object."<init>":()V
       4: return

  public void login(java.lang.String, java.lang.String);
    Code:
       0: invokestatic  #70                 // Method com/zhoujunwen/aop/LogAspect.aspectOf:()Lcom/zhoujunwen/aop/LogAspect;
       3: invokevirtual #76                 // Method com/zhoujunwen/aop/LogAspect.ajc$before$com_zhoujunwen_aop_LogAspect$2$9fd5dd97:()V
       6: aload_1
       7: ifnull        17
      10: aload_1
      11: invokevirtual #25                 // Method java/lang/String.length:()I
      14: ifne          28
      17: getstatic     #31                 // Field java/lang/System.out:Ljava/io/PrintStream;
      20: ldc           #37// String username cannot be empty
      22: invokevirtual #39                 // Method java/io/PrintStream.print:(Ljava/lang/String;)V
      25: goto          99
      28: aload_2
      29: ifnull        39
      32: aload_2
      33: invokevirtual #25                 // Method java/lang/String.length:()I
      36: ifne          50
      39: getstatic     #31                 // Field java/lang/System.out:Ljava/io/PrintStream;
      42: ldc           #37// String username cannot be empty
      44: invokevirtual #39                 // Method java/io/PrintStream.print:(Ljava/lang/String;)V
      47: goto          99
      50: ldc           #8                  // String zhoujunwen
      52: aload_1
      53: invokevirtual #45                 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
      56: ifeq          68
      59: ldc           #11                 // String 123456
      61: aload_2
      62: invokevirtual #45                 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
      65: ifne          79
      68: getstatic     #31                 // Field java/lang/System.out:Ljava/io/PrintStream;
      71: ldc           #49// String username or password incorrect
      73: invokevirtual #39                 // Method java/io/PrintStream.print:(Ljava/lang/String;)V
      76: goto          99
      79: getstatic     #31                 // Field java/lang/System.out:Ljava/io/PrintStream;
      82: ldc           #51// String logged in successfully
      84: invokevirtual #39                 // Method java/io/PrintStream.print:(Ljava/lang/String;)V
      87: goto          99
      90: astore_3
      91: invokestatic  #70                 // Method com/zhoujunwen/aop/LogAspect.aspectOf:()Lcom/zhoujunwen/aop/LogAspect;
      94: invokevirtual #73                 // Method com/zhoujunwen/aop/LogAspect.ajc$after$com_zhoujunwen_aop_LogAspect$1$9fd5dd97:()V
      97: aload_3
      98: athrow
      99: invokestatic  #70                 // Method com/zhoujunwen/aop/LogAspect.aspectOf:()Lcom/zhoujunwen/aop/LogAspect;
     102: invokevirtual #73                 // Method com/zhoujunwen/aop/LogAspect.ajc$after$com_zhoujunwen_aop_LogAspect$1$9fd5dd97:()V
     105: return
    Exception table:
       from    to  target type
           6    90    90   Class java/lang/Throwable

  public static void main(java.lang.String[]);
    Code:
       0: new           #1                  // class com/zhoujunwen/aop/AuthorizeService
       3: dup
       4: invokespecial #57                 // Method "<init>":()V
       7: astore_1
       8: aload_1
       9: ldc           #8                  // String zhoujunwen
      11: ldc           #11                 // String 123456
      13: invokevirtual #58                 // Method login:(Ljava/lang/String;Ljava/lang/String;)V
      16: return
}

SpringAOP

Introduction to Spring AOP

Spring AOP also enhances target classes and generates proxy classes. But the biggest difference with AspectJ is that Spring AOP runtime enhancements, while AspectJ is compile-time enhancements.

Uncle dolphin wrote that he had mistaken AspectJ as part of Spring AOP, and I think most people have not made clear the relationship between AspectJ and Spring AOP.

Spring AOP and Aspect Independence

When you don't use the annotations provided by Spring AOP, Spring AOP has nothing to do with AspectJ. The former is a JDK dynamic proxy, using CGLIB(Code Generation Library). CGLIB is a code generation library, which can dynamically generate a subclass of a class at runtime. The proxy pattern provides a way to access the target object, and when accessing the object, it introduces an indirect layer. The latter is a static proxy, which has been compiled into a bytecode file at the compilation stage. Spring provides pre-notification org.springframework.aop.MethodBeforeAdvice, post-notification org.springframework.aop.AfterReturning Advice, surrounded by notification org.aopalliance.intercept.MethodInvocation (achieved by reflection, invoke (org.aopalliance.intercept.MethodInvomi) in MethodInvocation to obtain information about target methods, target classes, target fields, etc.), exceptions Notify org. spring framework. aop. ThrowsAdvice. The core of Spring AOP is proxy. Its main implementation class is org. springframework. aop. framework. ProxyFactoryBean. Proxy Interfaces in ProxyFactoryBean are the target interface pointed by proxy. Spring AOP can not intercept methods in interfaces not specified by this attribute. Intereptor Names is the interceptor list, and get is the target interface implementation class. A proxy can only have one target.

Although the core class of Spring AOP, org. Spring framework. aop. framework. ProxyFactoryBean, can implement AOP behavior, it has limitations. It needs to explicitly call ProxyFactoryBean proxy factory class in code. For example, UserService is an interface, UserService Impl is an implementation class of UserService, Application Context is a Spring context, and the invocation method is Spring context. UserService userService = (UserService) context.getBean("userProxy"); and

The complete configuration is as follows:

<bean id="userService" class="com.zhoujunwen.UserServiceImpl"></bean>  

<!-- Define Pre-Notification,com.zhoujunwen.BeforeLogAdvice Realization org.springframework.aop.MethodBeforeAdvice -->  
<bean id="beforeLogAdvice" class="com.zhoujunwen.BeforeLogAdvice"></bean>  
<!-- Define post-notification, com.zhoujunwen.AfterLogAdvice Realization org.springframework.aop.AfterReturningAdvice -->  
<bean id="afterLogAdvice" class="com.zhoujunwen.AfterLogAdvice"></bean>  
<!-- Define exception notifications, com.zhoujunwen.ThrowsLogAdvice Realization org.springframework.aop.ThrowsAdvice-->  
<bean id="throwsLogAdvice" class="com.zhoujunwen.ThrowsLogAdvice"></bean>  
<!-- Define surround notifications, com.zhoujunwen.LogAroundAdvice Realization org.aopalliance.intercept.MethodInvocation -->  
<bean id="logAroundAdvice" class="com.zhoujunwen.LogAroundAdvice"></bean>  

<!-- Define the proxy class with the name userProxy,Through userProxy Accessing methods in business classes -->  
<bean id="userProxy" class="org.springframework.aop.framework.ProxyFactoryBean">  
    <property name="proxyInterfaces">  
        <value>com.zhoujunwen.UserService</value>  
    </property>  
    <property name="interceptorNames">  
        <list>           
         <value>beforeLogAdvice</value>  
         <!-- Woven post-notification -->  
         <value>afterLogAdvice</value>  
         <!-- Weave in exception notification -->  
         <value>throwsLogAdvice</value>  
         <!-- Weaving around notification -->  
         <value>logAroundAdvice</value>  
        </list>  
    </property>  
    <property name="target" ref="userService"></property>  
</bean>

Of course, the above limitation spring official also provides a solution to let AOP notifications be woven in without the service caller's knowledge, and can be automatically proxy through org. spring framework. aop. framework. autoproxy. BeanNameAutoProxyCreator.

<bean id="myServiceAutoProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">  
        <property name="interceptorNames">  
                <list>
                         <value>logAroundAdvice</value> 
                </list>  
        </property>  
        <property name="beanNames">  
                <value>*Service</value>  
        </property>  
</bean>  

The BeanNameAutoProxyCreator bean specifies that all service classes invoked in the context ending with Service are intercepted to execute the invoke method of logAroundAdvice. At the same time, it automatically generates service proxies, so that when it is used, it can directly fetch the beans of the service class, instead of replacing the beans of the rational class as above.

For the agent created by BeanNameAutoProxyCreator, you can call: UserService userService = context. getBean ("userService"); context is spring context.

Spring AOP and AspectJ

Spring AOP is related to AspectJ when you use annotations such as @Before, @After provided by Spring AOP. Two packages, org.aspectj:aspectjrt:1.6.11 and org.aspectj:aspectjweaver:1.6.11, were introduced in the development because Spring AOP uses AspectJ's Annotation, Aspect to define aspects, Pointcut to define entry points, and Advice to define enhancement processing. Although Spring AOP uses Aspect's Annotation, it does not use its compiler and weaver.

Spring AOP is based on JDK dynamic proxy, which generates proxy classes at runtime. To enable Spring's support for @AspectJ aspect configuration and ensure that the target Bean in the Spring container is automatically enhanced by one or more aspects, the following configuration must be added to the Spring configuration file

<aop:aspectj-autoproxy/>

When @AspectJ support is enabled, a Bean with @Aspect annotation is configured in the Spring container, and Spring automatically identifies the Bean and processes it as a tangent bean. Face beans are no different from ordinary beans in that they are configured with < beans.../> elements, and they support the use of dependency injection to configure attribute values.

Spring AOP annotations use demo

Full Annotation Implementation

Business logic code (AuthorizeService.java):

package com.zhoujunwen.engine.service;

import org.springframework.stereotype.Service;

/**
 * Created with IntelliJ IDEA.
 * Date: 2018/10/25
 * Time: 12:47 PM
 * Description:
 *
 * @author zhoujunwen
 * @version 1.0
 */
@Service
public class AuthorizeService {
    private static final String USERNAME = "zhoujunwen";
    private static final String PASSWORD = "123456";
    public void login(String username, String password) {
        if (username == null || username.length() == 0) {
            System.out.print("User name cannot be empty");
            return;
        }
        if (password == null || password.length() == 0) {
            System.out.print("User name cannot be empty");
            return;
        }
        if (!USERNAME.equals(username) || !PASSWORD.equals(password)) {
            System.out.print("Incorrect username or password");
            return;
        }
        System.out.print("Successful login");
    }
}

LogAspect. Java

package com.zhoujunwen.engine.service;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

/**
 * Created with IntelliJ IDEA.
 * Date: 2018/10/25
 * Time: 1:04 PM
 * Description:
 *
 * @author zhoujunwen
 * @version 1.0
 */
@Aspect
@Component
public class LogAspect {
    @After("execution(* com.zhoujunwen.engine.service.AuthorizeService.login(..))")
    public void logPointcut(){
        System.out.println("***Processing logs***");
    }
}

This implements a post-notification of the AuthorizeService.login() method. There is no need for other configurations in xml, of course, provided that the < aop: aspectj-autoproxy/> AspectJ automatic proxy is turned on.
Test call code:

AuthorizeService authorizeService = SpringContextHolder.getBean(AuthorizeService.class);
authorizeService.login("zhangsan", "zs2018");

xml configuration implementation

Business code, Log Buried Point (MeasurementService.java):

package com.zhoujunwen.engine.measurement;

import com.zhoujunwen.common.base.AccountInfo;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

/**
 * metrics Face Interface
 * @create 2018-08-16-10:13 a.m.
 */
@Service
public class MeasurementService {

    private static final Logger LOGGER = LoggerFactory.getLogger(MeasurementService.class);

    public String gainZhimaLog(AccountInfo accountInfo) {
        if (NumberUtils.isNumber(accountInfo.getZhimaPoint())) {
            return "normal";
        } else if (StringUtils.contains(accountInfo.getZhimaPoint(), "*")) {
            return "Unauthorized";
        } else {
            return "Not climbing up";
        }
    }

    public String gainJiebeiLog(AccountInfo accountInfo) {
        if (NumberUtils.isNumber(accountInfo.getJiebeiQuota())) {
            return "normal";
        }
        return "Not climbing up";

    }

    public String gainHuabeiLog(AccountInfo accountInfo) {
        if (accountInfo.getCreditQuota() != null) {
            return "normal";
        } else {
            return "Not climbing up";
        }
    }
}

Aspect logic, statistics of the total number of fields in the log (KeywordMeasurement.java):

package com.zhoujunwen.engine.measurement;

import com.zhoujunwen.common.base.AccountInfo;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;

/**
 * Keyword monitoring statistics < br >
 *
 * @create 2018-08-15-5:41 p.m.
 */
public class KeywordMeasurement {

    private String invokeCountFieldName = "";
    /**
     * Number of calls
     */
    public void summary(JoinPoint joinPoint, Object result) {
        try {

            String msg;
            String resultStr = "";
            if (result instanceof String) {
                resultStr = (String) result;
            }
            if (StringUtils.isBlank(resultStr)) {
                return;
            }
            if ("normal".equals(resultStr)) {
                msg = "_ok";
            } else if ("Not climbing up".equals(resultStr)) {
                msg = "_empty";
            } else {
                msg = "_star";
            }

            String methodName = joinPoint.getSignature().getName();
            Object args[] = joinPoint.getArgs();
            AccountInfo accountInfo = null;
            for (Object arg : args) {
                if (arg.getClass().getName().contains("AccountInfo")) {
                    accountInfo = (accountInfo) arg;
                }
            }
           
            if (methodName.contains("Zhima")) {
                invokeCountFieldName = "zhima" + msg;
            } else if (methodName.contains("Jiebei")) {
                invokeCountFieldName = "jiebei" + msg;
            } else if (methodName.contains("Huabei")) {
                invokeCountFieldName = "huabei" + msg;
            } else {
                return;
            }
            // TODO Writes to influxDB
        } catch (Exception e) {
            //skip
        }
    }
}

Complete configuration (post notification, and return results):

<bean id="keywordMeasurement" class="com.zhoujunwen.engine.measurement.KeywordMeasurement"/>

<aop:config proxy-target-class="true">
    <aop:aspect id="keywordMeasurementAspect" ref="keywordMeasurement">
        <aop:pointcut id="keywordMeasurementPointcut"
                      expression="execution(* com.zhoujunwen.engine.measurement.SdkMeasurementService.gain*(..))"/>
                <!-- Statistics summary,summary The method has two parameters JoinPoint and Object-->
        <aop:after-returning method="summary" returning="result" pointcut-ref="keywordMeasurementPointcut"/>
    </aop:aspect>
</aop:config>

Other available configurations (excluding aspects of rt, count, qps):

<! - Statistical RT,rt method has only one parameter ProceedingJoinPoint - >.
<aop:around method="rt" pointcut-ref="keywordMeasurementPointcut"/> 
<! -- counting the number of calls, the count method has only one parameter, JoinPoint - >.
<aop:after method="count" pointcut-ref="keywordMeasurementPointcut"/>
<! - Statistical QPS,qps method has only one parameter JoinPoint - >.
<aop:after method="qps" pointcut-ref="keywordMeasurementPointcut"/>

Note: In Spring AOP, the facet proxy class must be managed by Spirng container, so the delegate class also needs to be managed by Spring. It is not possible to put the delegate class instance into the container management created by oneself (such as in the Map created by oneself). If this is done, the facet will not take effect when the delegate class instance is called.
Reasons: (1) To implement the same interface as the target class, spring uses JDK's java.lang.reflect.Proxy class, which allows Spring to dynamically generate a new class to implement the necessary interface, weave notifications, and forward any calls to the target class.
(2) Generate subclass calls. Spring uses CGLIB libraries to generate a subclass of the target class. When creating this subclass, spring weaves notifications and delegates calls to the target class.

The Difference and Choice between AspectJ and Spring AOP

The Connection and Difference between the Two

AspectJ and Spring AOP both enhance the target class and generate proxy class.

AspectJ compiles aspect code into object code during compilation and belongs to static proxy; Spring AOP generates target class through proxy during run, and belongs to dynamic proxy.

AspectJ is a static proxy, so it can cut into final modified class and abstract modified class; Spring AOP is a dynamic proxy. Its implementation principle is to generate a proxy class inheriting the target class (delegate class) through CGLIB. Therefore, final modified class can not be proxyed, nor can static and final modified methods, because static and final methods can not be overridden. At the bottom of CGLIB, it actually relies on ASM, a very powerful Java bytecode generation framework. Discussions on CGLB and ASM will open a new chapter.

Spring AOP supports annotations, making it easier to create and configure facets using @Aspect annotations. With AspectJ, facets need to be created through. aj files, and code needs to be compiled using ajc (Aspect compiler).

Selective Contrast

First of all, Spring AOP is committed to providing an implementation of a face-to-face framework that can be tightly integrated with Spring IoC in order to solve common problems encountered in developing enterprise-level projects. Make it clear whether Spring beans or POJO s need to be addressed when applying cross-cutting concerns (such as things management, logging, or performance evaluation). If new applications are being developed, there is no resistance to choosing Spring AOP. But if you are maintaining an existing application that does not use the Spring framework, AspectJ will be a natural choice. To illustrate this point in detail, if you are using Spring AOP, when you want to add logging functionality to your application as an advice to track the process, then the advice can only be applied on Spring beans'Joinpoint.

Another factor to consider is whether you want to weave during compilation, post-compile or run-time. Spring only supports runtime weaving. If you have multiple teams developing multiple modules written in Spring (resulting in multiple jar files, such as one jar file per module), and one team wants to apply log notifications (where logs are only used to add cross-cutting concerns) to all Spring bean s (for example, jar files packaged by other teams) throughout the project. For example), this can be easily done by configuring the team's own Spring configuration file. This is possible because Spring uses runtime weaving.

Also, because Spring is based on the proxy pattern (using CGLIB), it has a limitation that crosscutting concerns cannot be applied on final-modified bean s. Because proxies need to inherit Java classes, once the keyword final is used, this will not be possible. In this case, you might consider using AspectJ, which supports compile-time weaving without generating agents. Similarly, it is impossible to apply cross-cutting concerns to static and final methods. Because Spring is based on proxy mode. If you configure notifications on these methods, runtime exceptions will result, because static and final methods cannot be overridden. In this case, you will also consider using AspectJ, because it supports compile-time weaving and does not need to generate proxies.

If you want to use an easy-to-implement approach, choose Spring AOP, because Spring AOP supports annotations, which make it easier to create and configure facets using @Aspect annotations. With AspectJ, you need to create facets through. aj files, and you need to use ajc (Aspect compiler) to compile code. So use Spring AOP if you are sure that the restrictions mentioned earlier will not be an obstacle to your project. An indirect limitation of AspectJ is that since AspectJ notifications can be applied to POJO s, it is possible to apply notifications to a configured notification. For a notification that you haven't noticed the wide application of this aspect, it can lead to an infinite loop. In this case, when proceed is about to be invoked, the log notification is applied again, which results in a nested loop.

public aspectLogging {
  Object around() : execution(public * * (..))
  Sysytem.out.println(thisJoinPoint.getSignature());
  return proceed();
}

Reference Articles

Sincerely thank the following articles and authors, but also let me learn a lot in the process of reference practice and theoretical summary. Don't be a mindless plagiarist. Read other people's articles, absorb the essence, and draw conclusions through personal practice. Respect the original, respect the author!

AspectJ(1) Some concepts to understand
AspectJ framework is much better than AOP with spring.
Comparative Analysis of the Differences between Spring AOP and AspectJ
Basic usage of AspectJ
Application of Spring AOP (I)
AspectJ official doc document
Spring AOP,AspectJ, CGLIB are a little dizzy

<script src="https://my.openwrite.cn/js/re...; type="text/javascript"></script>
<script>

const btw = new BTWPlugin();
btw.init({
    id: 'main',
    blogId: '16456-1570500048991-724',
    name: 'Rain is like playing the piano.',
    qrcode: 'https://www.zhoujunwen.com/wp-content/uploads/2019/09/qrcode_for_gh_f7c7e6ace303_258-1.jpg',
    keyword: 'Read the whole passage',
});

</script>

First issue of this article "A Valley of Vanity" Personal blog, please sign before reprinting, reprinting please indicate the source.

The ancient goodness is Taoist, subtle and mysterious, deep and unconscious. The husband is only incognizable, so he is willing to do so.

If Yuluo wades through the river in winter, he is still fearful of his neighbors, as if he were a guest, as if he were interpreted by ice, as if he were simple, as if he were open, as if he were valley, and as if he were muddy.

Which can be muddy to quiet Xu Qing? Which can move Xusheng safely?

Keep this way. The only way to make a new man is to make a better man.

Please pay attention to my Wechat Public Number: Rain is like playing the piano, Thanks

Posted by juline on Wed, 09 Oct 2019 03:45:08 -0700