banner
RustyNail

RustyNail

coder. 【blog】https://rustynail.me 【nostr】wss://ts.relays.world/ wss://relays.world/nostr

Simple AOP module (implemented with cglib)

Implementing a simple AOP module using cglib

There are still some issues with "around".

Jar Package#

The jar package "cglib-nodep-2.1_3" is required, or you can use Maven by adding the following dependency:

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.2.4</version>
</dependency>

The version may vary depending on the situation.

Target Class#

Assuming we have a target class like this:

public class TestTarget {
    public void out(String a) {
        System.out.println("Target out."+a);
    }
}

The TestTarget class has an "out" method, and we want to log something when the "out" method is executed.

Enhancer#

The Enhancer can enhance the original methods and return a new object.

Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(TestTarget.class);
enhancer.setCallback(callback);

The code creates an enhancer and passes a "Class" object to it. What the enhancer does with it is not important for now. Then, a callback is passed to it. The callback is defined as follows:

public class BeforeCallBack implements MethodInterceptor {
    public BeforeCallBack() {
       
    }
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        // do something here.
        return methodProxy.invokeSuper(o, objects);
    }
}

The BeforeCallBack implements the MethodInterceptor interface. This is where the actual enhancement happens. Before returning the original method, do something (this is the before pointcut, but it can be changed to after or around).

Effect:

Here, the anonymous inner class implementation is replaced with a lambda expression.

public class MainClass {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(TestTarget.class);
        enhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> {
            System.out.println("before.");
            return methodProxy.invokeSuper(o,objects);
        });
        TestTarget testTarget = (TestTarget) enhancer.create();
        testTarget.out();
    }
}

class TestTarget{
    public void out(){
        System.out.println("out. ");
    }
}

before.
out. 

Generalization#

  • Pointcut

When enhancing, we did not specify which method to enhance, so all methods in the class will be affected. Cglib provides a CallbackFilter to differentiate which methods should use which Callback (before, after, etc.). The most suitable way to mark method types is through annotations.

  • Aspect

After intercepting a method, we perform some operations before and after it returns. We write the desired operations in the intercept method. In other words, for each Callback requirement, we need to manually implement the interface and add the business code. Therefore, we should extract the business code.

Abstract the business into an aspect, such as logging. We have a LogAspect that extends AbstractAspect. In the intercept method, we only need to call the abstract method.

For example:

public class BeforeCallBack implements MethodInterceptor {
    Class<? extends AbstractAspect> aspect;

    public BeforeCallBack(Class<? extends AbstractAspect> aspect) {
        this.aspect = aspect;
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        AbstractAspect instance = aspect.newInstance();
        instance.doBefore();
        return methodProxy.invokeSuper(o, objects);
    }
}

Regardless of the actual aspect, it is an AbstractAspect.

  • Annotation Parsing

The main annotations are "Aspect" and "PointCut". "Aspect" is used to mark which aspect should be applied to the TargetClass, and "PointCut" is used to mark the type of the method pointcut (before, after, etc.).

Demo#

Gitee Demo

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.