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();
}
@Override
protected 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;
}
@Override
public 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;
}
@Override
public 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();
}
@Override
public 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的原创文章,请关注公众号"汪子熙":
相关推荐
Spring AOP面向方面编程原理Spring AOP面向方面编程原理Spring AOP面向方面编程原理Spring AOP面向方面编程原理Spring AOP面向方面编程原理Spring AOP面向方面编程原理Spring AOP面向方面编程原理
Spring,面向切面编程AOP例子!AOP(Aspect Oriented Programming)!
Spring面向切片编程代码;Spring面向切片编程代码;Spring面向切片编程代码;
AOP编程例子,拦截器。AOP控制权限编程例子
AOP 面向服务 面向方面编程 AOP 面向服务 面向方面编程 AOP 面向服务 面向方面编程 AOP 面向服务 面向方面编程
Spring 动态代理和aop切面编程例子,自己写的例子!!!!!!!
AOP是OOP的延续,是(Aspect Oriented Programming)的缩写,意思是面向切面编程。 OO注重的是我们解决问题的方法(封装成Method),而AOP注重的是许多解决问题的方法中的共同点,是对OO思想的一种补充! 主要的功能是:...
NULL 博文链接:https://sammor.iteye.com/blog/1054464
Spring-aop面向切面编程实例 日志系统,权限控制等.
AOP面向切面编程实例,可当作业提交。.net代码亲测,完全正确运行。
关于Spring框架的aop简介
Spring AOP面向方面编程原理:AOP概念,主要介绍面向对象的概念及原理,及作者的一些理解。
aop,面向切面编程
AOP 及其相关的工具使您可以将基本横切关注点(如日志记录和安全)的代码,与程序的核心应用逻辑相分离。AOP 通过使代码更具有可读性、更不容易出错以及更容易设计和维护,改善了代码质量 本教程介绍: 使用 AOP 的...
spect Oriented Programming(AOP),面向切面编程,是一个比较热门的话题。AOP主要实现的目的是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的...
AOP 面向方面编程 技术总结 AOP 面向方面编程 技术总结
2.1 面向切面编程AOP入门 软件系统中的一些功能需要用到应用程序的多个地方,但是我们又不想在每个点都明确调用它们。日志、安全和事务管理的确都很重要,但它们是否为应该被应用对象主动调用呢?如果让应用对象只...
spring aop应用 spring aop应用 spring aop应用 spring aop应用 spring aop应用
面向横截面编程面向横截面编程面向横截面编程面向横截面编程面向横截面编程
AOP+Sample 实现AOP的一个例子