面向切片程式設計(AOP)應用的一些實際例子
The definition of AOP in wikipedia seems a little bit difficult for beginners to understand, so in this blog I use an example to introduce why we need it.
Suppose I have an order command class which performs its core business logic in method doBusiness:
package aop;import java.util.logging.Level;import com.sun.istack.internal.logging.Logger;public class OrderCommand {
public void execute(){
Logger logger = Logger.getLogger(OrderCommand.class);
logger.log(Level.INFO, "start processing");
// authorization check logger.log(Level.INFO, "authorization check");
logger.log(Level.INFO, "begin performance trace");
// only this line implements real business logic this.doBusiness();
logger.log(Level.INFO, "end performance trace");
}
private void doBusiness(){
System.out.println("Do business here");
}
public static void main(String[] args) {
new OrderCommand().execute();
}}
In method execute(), it is flooded with too many non-functional code like logging, authorization check and performance trace.
It is not a good design, we can try to improve it via template method pattern.
Template method pattern
With this pattern, I create a new parent class BaseCommand, and put all non-functional code inside the execute method.
import java.util.logging.Level;import com.sun.istack.internal.logging.Logger;public abstract class BaseCommand {public void execute(){
Logger logger = Logger.getLogger(this.getClass());
logger.log(Level.INFO, "start processing");
// authorization check logger.log(Level.INFO, "authorization check");
logger.log(Level.INFO, "begin performance trace");
// only this line implements real business logic this.doBusiness();
logger.log(Level.INFO, "end performance trace");}protected abstract void doBusiness();}
Now the real business logic is defined in child class OrderCommand, whose implementation is very clean:
public class OrderCommand extends BaseCommand {public static void main(String[] args) {
new OrderCommand().execute();}@Overrideprotected void doBusiness() {
System.out.println("Do business here");}}
Drawback of this solution: as the parent class has defined the template method execution, it is NOT possible for a child class to adapt it, for example, a child class cannot change the order sequence of authorization check and performance trace method. And suppose a child class does not want to implement authorization check at all – this could not be achieved with this solution. We have to use decorator pattern instead.
Decorator pattern
First I need to create an interface:
public interface Command {public void execute();}
And create a decorator to cover the log and authorization check function:
import java.util.logging.Level;import com.sun.istack.internal.logging.Logger;public class LoggerDecorator implements Command{private Command cmd;public LoggerDecorator(Command cmd){
this.cmd = cmd;}@Overridepublic void execute() {
Logger logger = Logger.getLogger(this.getClass());
logger.log(Level.INFO, "start processing");
// authorization check logger.log(Level.INFO, "authorization check");
this.cmd.execute();}}
And a second decorator for performance trace:
package aop;import java.util.logging.Level;import com.sun.istack.internal.logging.Logger;public class PerformanceTraceDecorator implements Command{private Command cmd;public PerformanceTraceDecorator(Command cmd){
this.cmd = cmd;}@Overridepublic void execute() {
Logger logger = Logger.getLogger(this.getClass());
logger.log(Level.INFO, "begin performance trace");
this.cmd.execute();
logger.log(Level.INFO, "end performance trace");}}
And the class to finish the real business logic. Now I have the full flexibility to constructor the instance according to real business case, with the help of different decorator. The following instance fullCmd owns the ability of both authorization check log and performance trace.
public class OrderCommand implements Command {public static void main(String[] args) {
Command fullCmd = new LoggerDecorator( new PerformanceTraceDecorator( new OrderCommand()));
cmd.execute();}@Overridepublic void execute() {
System.out.println("Do business here");}}
Suppose in a given scenario, only performance trace is needed, we can just use the performance trace decorator:
Command cmd = new PerformanceTraceDecorator( new OrderCommand());cmd.execute();
Drawback of decorator pattern: The decorator class and the business class have to implement the same interface, command, which is more business related. Is there possibility that the utility classes for non-functional implementation can just work without implementing the same interface which is implemented by business class?
AOP solution
I use a Java project implemented by Spring framework to demonstrate the idea.
Suppose I hope to add performance trace on this business method: save.
(1) You may have already observed the annotation @Log(nameI042416=”annotation for save method”) used in line10. This annotation is declared in file Log.java:
(2) Now I have to declare an Aspect class which contains a pointcut. A pointcut tells Spring framework which methods could be applied with AOP strategy, and the class annotated with @Aspect contains methods which should be called by Spring framework to “decorate” the methods identified by annotation. Here below I have declared a pointcut “logJerry” via annotation @Pointcut:
For example, since we have annotated the business method save() with “@Log(nameI042416=”annotation for save method”)”, we can define what logics must be done on it, with the help of @Before and @After plus declared pointcut.
With this approach, I can add performance trace function to save method without modifying its source code.
Set breakpoint on these beforeExec and afterExec methods, launch the project with Tomcat under debug mode, paste the following url to your browser: http://localhost:9498/springaop/aopRootJerry/aop2Jerry/i042416?string=sap Through callstack you can understand how the AOP call is working in Spring.
Why we say AOP can increase modularity by allowing the separation of cross-cutting concerns?
Suppose we have lots of methods all of which need common utilities like log, performance trace and authorization check. Before we use AOP, these utilities are scattered in every method:
After AOP is used, those common stuff are extracted into Aspect class and reusability is fulfilled. From the picture below we can see the cross-cutting concerns are now separated.
要獲取更多Jerry的原創文章,請關注公眾號"汪子熙":
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/24475491/viewspace-2724088/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Spring AOP:面向切面程式設計的核心概念與實際應用Spring程式設計
- aop面向切面程式設計的實現程式設計
- AOP(面向切面程式設計)程式設計
- AOP 面向切面程式設計程式設計
- Util應用框架基礎(三) - 面向切面程式設計(AspectCore AOP)框架程式設計
- Spring 面向方面程式設計 AOPSpring程式設計
- AOP--面向切面程式設計程式設計
- Java中的面向切面程式設計(AOP)Java程式設計
- 設計模式之面向切面程式設計AOP設計模式程式設計
- 前端js面向切面程式設計(AOP)前端JS程式設計
- Spring之AOP面向切面程式設計Spring程式設計
- spring AOP 程式設計式應用Spring程式設計
- Spring Boot實戰系列(3)AOP面向切面程式設計Spring Boot程式設計
- 前端解讀面向切面程式設計(AOP)前端程式設計
- 01.AOP(AspectOrientatedProgramming面向切面程式設計)程式設計
- Spring AOP——Spring 中面向切面程式設計Spring程式設計
- JS實現AOP 面向切面程式設計 (裝飾者模式)JS程式設計模式
- Spring Boot中面向方面程式設計 (AOP)教程Spring Boot程式設計
- Spring AOP(面向切面程式設計)是什麼?Spring程式設計
- .NET Core 實現動態代理做AOP(面向切面程式設計)程式設計
- Spring 面向切面程式設計AOP 詳細講解Spring程式設計
- 手寫Spring---AOP面向切面程式設計(4)Spring程式設計
- 手寫Spring---AOP面向切面程式設計(3)Spring程式設計
- 面向協議程式設計的一些思考協議程式設計
- 基於SpringBoot AOP面向切面程式設計實現Redis分散式鎖Spring Boot程式設計Redis分散式
- Day67 Spring AOP(面向切面程式設計) 和代理設計模式Spring程式設計設計模式
- Unity應用架構設計(12)——AOP思想的實踐Unity應用架構
- Angular Ngrx Store 應用程式狀態的一些典型例子Angular
- AOP程式設計實戰-AspectJ程式設計
- 面向面試題和實際應用談Promise面試題Promise
- AOP程式設計之AspectJ介紹及在Android中的應用程式設計Android
- Python非同步IO程式設計之-asyncio協程應用例子Python非同步程式設計
- framebuffer應用程式設計實踐程式設計
- 程式設計思想 面向切面程式設計程式設計
- Angular @Inject 註解的實際應用例子和工作原理淺析Angular
- 面向介面程式設計實踐之aspnetcoreapi的抽象程式設計NetCoreAPI抽象
- [翻譯] 響應式程式設計(Reactive Programming) - 流(Streams) - BLoC - 實際應用案例程式設計ReactBloC
- 面向介面程式設計程式設計