Introduction to the

AspectJ is a section-oriented framework that extends the Java language. AspectJ defines the AOP syntax, which has a specialized compiler for generating Class files that comply with the Java byte-encoding specification. Using AOP, each part of the business logic can be isolated, thus reducing the degree of coupling between each part of the business logic, improving the reusability of the program, and improving the efficiency of development.

The main function

Data burial points, logging, performance statistics, security controls, transaction handling, exception handling, and more

Purpose (Why Use AspectJ)

By separating logging, performance statistics, security controls, transaction handling, exception handling, etc., from the business logic code, we hope to separate these behaviors into methods that do not guide the business logic, and thus change these behaviors without affecting the business logic code.

The principle of

AspectJ scans the target program during compilation, weaves the Aspect program written by the developer into the target program’s.class file, and reconstructs the target program (in JoinPoint). The purpose of AOP is to establish the connection between the object program and the Aspect program (to obtain the context information of the object, method, parameter, etc.) to achieve the purpose of AOP.

Gradle configuration example

The two most important packages to introduce AspectJ into the Android project are:

// Add the wetter to Buildscript, gradle builds the class file to be weaved. // Add the toolkit to BuildScript to perform some tasks while building the project: typing logs, etc

classpath 'org. Aspectj: aspectjtools: 1.8.11'
classpath 'org. Aspectj: aspectjweaver: 1.8.9'
Copy the code

// Add the dependency to dependencies, providing the @aspectJ syntax

compile 'org. Aspectj: aspectjrt: 1.8.9'
Copy the code

// Gradle in app

import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main
Copy the code

// Prints gradle logs

android.applicationVariants.all { variant -> JavaCompile javaCompile = variant.javaCompile javaCompile.doLast { String[]  args = ["-showWeaveInfo"."1.5"."-inpath", javaCompile.destinationDir.toString(),
                         "-aspectpath", javaCompile.classpath.asPath,
                         "-d", javaCompile.destinationDir.toString(),
                         "-classpath", javaCompile.classpath.asPath,
                         "-bootclasspath", project.android.bootClasspath.join(
                File.pathSeparator)]

        MessageHandler handler = new MessageHandler(true);
        new Main().run(args, handler)

        def log = project.logger
        for (IMessage message : handler.getMessages(null.true)) {
            switch (message.getKind()) {
                case IMessage.ABORT:
                case IMessage.ERROR:
                case IMessage.FAIL:
                    log.error message.message, message.thrown
                    break;
                case IMessage.WARNING:
                case IMessage.INFO:
                    log.info message.message, message.thrown
                    break;
                case IMessage.DEBUG:
                    log.debug message.message, message.thrown
                    break; }}}}Copy the code

AspectJ official website configuration

Fernandocejas.com/2014/08/03/…

grammar

Aspect – the Aspect

In AOP, an aspect is the logical processing by which the tag performs the pointcut tag method. It is the module in the aspect of the specific logic to be dealt with at the pointcut.

Join point – JoinPoint

JoinPoint is a chain of execution. Each JoinPoint is a separate closure that assigns context to the closure’s execution method body logic during execution.

AspectJ joinPoint has the following:

The constructor call executes field get to get a variable field set Setting a variable, pre-initialization Object, does some work in the constructor. The static Initialization Object does a lot of work in the initialization constructor. The static initialization class initializes handler exceptions such as try catch(XXX). Advice Execution within a catch has 3 tokens (Around Before After)Copy the code

Point of tangency, PointCut

The Pointcut declaration determines the set of JoinPoints that need to be cut. Pointcut controls which advice you apply to joinPoints, usually using regular expressions to match applications, and determines which JointPoints will get notified. Call, execution, target, this, within, etc.

Within (TypePattem) TypePattern identifies package or class. TypePatter can use wildcards withincode (ConstructorSignaturelMethodSignature) says a constructor or other functions involved in the implementation process of JPoint cflow pointcuts) Cflow refers to a pointcut cflowbelow(pointcuts), which does not include the pointcuts JPoint itself This (Type) JPoint's this object is of Type. Target (Type) JPoint's target object is of Type. Args (TypeSignature) is used to search JPoint parameters conditionallyCopy the code

Match rule

(1) Syntax type matching wildcard: * : matches any number of characters; . : matches any number of repetitions of characters, such as any number of subpackages in a type pattern; Matches any number of parameters in the method parameter pattern. + : matches a subtype of the specified type; Can only be placed after a type pattern as a suffix. AspectJ use and (&), or (| |), not (!) To combine pointcut expressions.

(2) Match pattern call(< annotation? > < modifier? > < return value type > < type declaration? >.< method name >(parameter list) < exception list >?

Exact match // matches all public void methods annotated by @describe in the com.sunmi.MainActivity class. The @pointcut (" call (@ the Describe public void. Com sunmi. MainActivity. The init (Context)) ") public void Pointcut () {} a single fuzzy match / / means to match All public void methods annotated by @describe in the com.sunmi.MainActivity class. @Pointcut("call(@Describe public void com.sunmi.MainActivity.*(..) ) ") public void pointCut(){} public void pointCut(){ And that subclass is in the package name starting with com.sunmi @pointcut ("call(* Android.widget.toast +.show(..)) ) && (within(com.sunmi.. *))") public void toastShow() {} public void toastShow() {} public void toastShow() { @pointcut ("execution(* *.. Activity+.onStart(..) )&& within(com.sunmi.*)") public void onStart(){}Copy the code

The sample code

annotated

Declare an annotation AopPoint

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface AopPoint {
        String value(a);
        int type(a) default 0;
    }
Copy the code

In the Activity, we define two button click events, annotate the methods, and specify value and Type.

    @AopPoint(value = "Home click",type = 1)
    public void doFunc1(View view) {
        SystemClock.sleep(1000);
    }

    @AopPoint("Click by category")
    public void doFunc2(View view) {
        SystemClock.sleep(1000);
    }
Copy the code

Write a facet class

    @Aspect
    public class AopAspect {
    @Pointcut("execution(@com.example.davis.aspectdemo.AopPoint * *(..) )")
    public void aopCut(a){}@Around("aopCut()")
    public Object dealMethod(ProceedingJoinPoint joinPoint) throws Throwable {

        MethodSignature signature= (MethodSignature) joinPoint.getSignature();
        AopPoint aopPoint=signature.getMethod().getAnnotation(AopPoint.class);

        String value=aopPoint.value();
        int type=aopPoint.type();

        TimeTool timeTool=new TimeTool();
        timeTool.start();

        Object result=joinPoint.proceed();

        timeTool.stop();
        Log.e("aopCut",value+"Execution time ="+timeTool.getTotalTimeMillis() +"Type is the type"+type);

        returnresult; }}Copy the code

The results of

No annotations

This is a call to the onCreate method in the scanning Activity

    @Aspect
    public class FuncTAspect {

    @Before("execution(* android.app.Activity.onCreate(..) )")
    public void onActivityMethodBefore(JoinPoint joinPoint) throws Throwable {
        String key = joinPoint.getSignature().toString();

        Log.e("FuncTAspect"."onActivityMethodBefore: " + key+"\n"+joinPoint.getThis()); }}Copy the code

Only the onCreate method can be scanned as a result

If change the onCreate to wildcard * android. App. Activity. The onCreate (..) Into the android app. The Activity. * (..)

The results of

2. Catch exceptions

    @Aspect
    public class ExceptionHandleAspect {

    private static final String TAG = "ExceptionHandleAspect";

    /** * Intercepted null pointer exception **@param e
     */
    @Pointcut("handler(java.lang.Exception)&&args(e)")
    public void handle(Exception e) {}/** * Do some processing before the catch code executes **@param joinPoint
     * @paramE Abnormal parameter */
    @Before(value = "handle(e)", argNames = "e")
    public void handleBefore(JoinPoint joinPoint, Exception e) {
        Log.e(TAG, joinPoint.getSignature().toLongString() + " handleBefore() :" + e.toString());
    }
    }
Copy the code

Creates a Null pointer in the method

    public void doFunc1(View view) {
        try {
            AppItem appItem=null;
            appItem.number=2;
        }catch (Exception e){}

    }
Copy the code

The results of

code

Github.com/xusoku/Aspe…

Refer to the link

AOP AspectJ technology principle detailed explanation and actual combat summary