# 4.2 Interceptor

# 1. Basic Usage

An Interceptor can intercept methods, providing an opportunity to add aspect code before and after the method, achieving the core goal of AOP. The Interceptor interface only defines one method: public void intercept(Invocation inv). Here's a simple example:

public class DemoInterceptor implements Interceptor {
    public void intercept(Invocation inv) {
       System.out.println("Before method invoking");
       inv.invoke();
       System.out.println("After method invoking");
    }
}
1
2
3
4
5
6
7

In the code above, the DemoInterceptor will intercept the target method and output text to the console both before and after the method's invocation. The line inv.invoke() is the call to the target method; inserting aspect code before and after this line can easily implement AOP.

Note: You must call the inv.invoke() method to pass the current call to subsequent Interceptors and the Action.

Common Mistake: To date, many students forget to call the inv.invoke() method, resulting in the action in the controller not being executed. Here's another reminder: always call inv.invoke() once, unless you deliberately avoid calling the remaining interceptors and action. In such cases, you still need to use inv.getController().render()/renderJson() to call the related render() method to respond to the client.

Invocation, as the only parameter in the Interceptor interface's intercept method, offers many convenient methods to use in the interceptor. Here are the methods in Invocation:

Method Description
void invoke() Pass this call and invoke the remaining interceptors and the target method
Controller getController() Get the Controller object for the Action call (only for control layer interception)
String getActionKey() Get the action key value for the Action call (only for control layer interception)
String getControllerKey() Get the Controller key value for the Action call (only for control layer interception)
String getViewPath() Get the view path for the Action call (only for control layer interception)
<T> getTarget() Get the object to which the intercepted method belongs
Method getMethod() Get the Method object of the intercepted method
String getMethodName() Get the method name of the intercepted method
Object[] getArgs() Get all parameter values of the intercepted method
Object getArg(int) Get the specified index parameter value of the intercepted method
<T> getReturnValue() Get the return value of the intercepted method
void setArg(int) Set the specified index parameter value of the intercepted method
void setReturnValue(Object) Set the return value of the intercepted method
boolean isActionInvocation() Determine if it's an Action call, i.e., control layer interception

Please correct a typo in the third line from the bottom in the screenshot above: setArg(int) should be changed to setArg(int, Object).

Note: In version 4.9.03 of jfinal, getControllerKey() was renamed to getControllerPath(). The original method is still available and can be used. The renaming to getControllerPath() allows multiple Controllers to share the same controllerPath value.

# 2. Global Sharing and Thread Safety

Interceptors are globally shared. Therefore, if you use attributes within them, you must ensure that these attributes are thread-safe. The following code is incorrect:

public class MyInterceptor implements Interceptor {
 
   private int value = 123;
   
   public void intercept(Invocation inv) {
       // Multiple threads will access the value concurrently, causing confusion
       value++;
       
       inv.invoke();
   }
}
1
2
3
4
5
6
7
8
9
10
11

As shown in the code above, the value attribute will be accessed by multiple threads, leading to thread safety issues.

Last Updated: 9/17/2023, 6:05:19 AM