- Developing Middleware in Java EE 8
- Abdalla Mahmoud
- 713字
- 2021-07-23 19:24:34
Using interceptors
Interceptors, as the name suggests, are methods that intercept other methods. With interceptors, you can write one method that will always run before one or other methods of your choice. Interceptors are useful when you are required to implement some cross-cutting concern, which should take kind of a global effect on some other scenarios. For example, suppose you want to log each method call in a payment processor bean, so you can later check what really happened during runtime in production. The direct mechanism to implement this is to write a logging function, then call it in each method in the payment processing bean. Although this seems simple, it's really redundant with the existence of interceptors. With interceptors, you can write your logging function once, and attach it with all other methods that you need to associate logging with. Interceptors also allow you to access the original method invocation context; this means that you can access parameters passed to the original method. Moreover, interceptors enable you to take control of the invocation itself, such as blocking the method invocation or even altering the return value.
Interceptors in CDI are a direct implementation to the aspect-oriented programming technique, you can also think of interceptors — recalling knowledge you may have with the servlets APIs, such as filters you map to servlets or JSPs. Filters intercept HTTP requests, and so do interceptors on CDI methods.
Common use cases of interceptors are:
- Logging
- Profiling
- Transaction management
- Authorization
Let's define our first CDI interceptor. Write a class called MyInterceptor with the following code:
public class MyInterceptor { @AroundInvoke public Object interceptMethod(InvocationContext ctx) throws Exception { Object retValue = ctx.proceed(); return "Intercepted! " + retValue; } }
interceptMethod(), annotated with @AroundInvoke, is the method that is going to intercept some other methods. @AroundInvoke tells the container that this method is an intercepting one, which will always run each time before some other methods get executed upon a user call.
In this intercepting method, you can do some pre and/or post operations, handle parameter's values, alter the return value, and even ban the original method call itself! The InvocationContext parameter is the object that you can use to retrieve the original method call information, and the most important part, proceeding with the original method call. The proceed() method in the InvocationContext object is used to
proceed the method call to the original one; note that if you did not call it, the intercepted method itself will not be called.
The next step is to associate this interceptor with some other methods. Recalling the MyPojo example, we will use the @Interceptors annotation to associate MyInterceptor with the getMessage method as follows:
@Dependent public class MyPojo { @Interceptors(MyInterceptor.class) public String getMessage() { return "Hello from MyPojo!"; }
By annotating the getMessage() method with the @Interceptors annotation, we tell the container that we wish to intercept the getMessage() method with the MyInterceptor interceptor. This means that whenever a call to getMessage() is performed, interceptMethod (annotated with @AroundInvoke in the MyIntercptor class) will be called.
Now, if we injected the MyPojo bean in our example servlet, and tried to print the getMessage() return value, we would get the following output:
Intercepted! Hello from MyPojo!
As you see, interceptMethod has called the original method, read its return value, altered it, and then returned it to us, prefixed with the string Intercepted!.
You can also apply an interceptor to a complete class, by annotating the class itself with the @Interceptors annotation as follows:
@Dependent @Interceptors(MyInterceptor.class) public class MyPojo { public String getMessage1() { return "MyPojo first message!"; } public String getMessage2() { return "MyPojo second message!"; } }
Now, all the methods in the MyPojo bean are intercepted using the MyInterceptor annotation. When trying to call any of them, the interceptMethod will intercept and produce the desired effect. Let's try to use MyPojo from our example servlet:
@WebServlet(urlPatterns = "/cdi-example") public class ExampleServlet extends HttpServlet { @Inject private MyPojo myPojo; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.getOutputStream().println(myPojo.getMessage1()); resp.getOutputStream().println(myPojo.getMessage2()); } }
This will be the output, as expected:
Intercepted! MyPojo first message!
Intercepted! MyPojo second message!
- Instant Node Package Manager
- JavaScript從入門到精通(微視頻精編版)
- 機器學習系統:設計和實現
- 自己動手實現Lua:虛擬機、編譯器和標準庫
- Oracle Database In-Memory(架構與實踐)
- Mastering Scientific Computing with R
- 編寫高質量代碼:改善C程序代碼的125個建議
- 大學計算機基礎(第2版)(微課版)
- Active Directory with PowerShell
- LabVIEW虛擬儀器入門與測控應用100例
- 零基礎學HTML+CSS
- C編程技巧:117個問題解決方案示例
- PyQt編程快速上手
- 現代C:概念剖析和編程實踐
- 超好玩的Scratch 3.5少兒編程