本人菜鸡一个,写这个系列的文章是为了通过把自己理解AOP的心路历程记录下来,加深自己对这个思想的印象~
背景:
其实一开始听到AOP这个概念的时候,是自己刚学java没多久的时候,那时候很懵逼啊,这都什么鬼啊?
所以写这篇文章的时候,希望能够把自己理解的线路描绘出来。
一、我们从代码简洁和优化的初衷!
来往后看,理解什么是AOP思想!
举个例子,当我们一个java代码被调用的时候,我想记录一些指标(其实不就是打印日志需求)
public void functionA(){
System.out.println("functionA调用开始")
//方法逻辑....
System.out.println("functionA调用结束")
}
很简单,这样就可以完成我们的需求。
二、然后我们开始想,如何优化这个功能?
1、不使用System.out.print来打印,想用一些封装的打印类
当然我们可以自己实现一个打印类,或者使用现有的,比如log4j
private static final Logger logger = LoggerFactory.getLogger(当前类.class);
public void functionA(){
logger.info("functionA调用开始")
//方法逻辑....
logger.info("functionA调用结束")
}
2、甚至我们觉得直接这样调用不好(想让打印出来的日志格式统一),因此我们写了方法来封装他
private static final Logger logger = LoggerFactory.getLogger(当前类.class);
public void printLog(String type,String funcName){
if(type=="start"){
logger.info(funcName+"调用开始")
}else{
logger.info(funcName+"调用结束")
}
}
public void functionA(){
printLog("start","functionA")
//方法逻辑....
printLog("end","functionA")
}
public void functionB(){
printLog("start","functionB")
//方法逻辑....
printLog("end","functionB")
}
到此为止,你已经做出了两步优化,这是在代码改动最少的情况下,能做出的最大的优化!
三、有没有更好的优化方法?
我想要实现那种,只需要写代码逻辑,然后日志这些乱七八糟的东西,我不需要用代码来指定打印,自动打印就好了。
如果你有这种想法的话,恭喜,AOP就是因为这种想法诞生的!
这里暂且不讨论在spring中如何使用aop的注解来实现日志的打印
我们来想想,就上面的那部分代码如何优化?
-1、做一个抽象类,实现了打印日志的具体方法,并且留下一个run方法给实现类实现
public abstract class CommonJob {
public Logger logger ;
protected CommonJob( Logger logger) {
this.logger = logger;
}
public void beforeLog(){
logger.info("调用开始")
}
public void afterLog(){
logger.info("调用结束")
}
public void error(){
logger.error("调用失败")
}
public abstract void run();
}
-2、必须有个地方调用打印日志和run方法
public class CommonAnalyzer {
public void runJob(CommonJob job){
try{
job.beforeLog();
job.run();
job.afterLog();
} catch (Exception e) {
job.error(e);
}
}
}
-3、然后调用
public class AModelAnalyzer extends CommonAnalyzer {
private static final Logger logger = LoggerFactory.getLogger(当前类.class);
public void functionA(){
runJob(new CommonJob(logger){
@Override
public void run() {
//具体代码逻辑
//balabalabala....
}
});
}
public void functionB(){
runJob(new CommonJob(logger){
@Override
public void run() {
//具体代码逻辑
//balabalabala....
}
});
}
public static void main(String[] args){
functionB();
functionA();
}
}
这样,我们就只需要在调用runJob方法的时候传入CommonJob类的实现类,或者在runJob中实现一个匿名内部类!
-4、甚至当处理逻辑一样的时候,我们可以写一个CommonJob的实现类,这样就可以复用相同的run代码,
好比这样!
public class SelfCommonJob extends CommonJob {
//当有一些处理逻辑一样的不同模块的job,
//可以写一些参数,在run执行的时候做判断
public SelfCommonJob(Logger logger){
}
//实现run
public void run(){
//代码逻辑...
}
}
public class AModelAnalyzer extends CommonAnalyzer {
private static final Logger logger = LoggerFactory.getLogger(当前类.class);
private SelfCommonJob scj = new SelfCommonJob (logger);
public void functionA(){
runJob(scj);
}
public void functionB(){
runJob(scj);
}
public static void main(String[] args){
functionB();
functionA();
}
}
当然这只是很基础的模型,但是这就是AOP的思想,程序员调用这个方法的时候,只需要关注run方法里面的代码逻辑就可以了,不需要关注其他打印日志,判断执行时间等等一系列的事情!我觉得还是蛮方便的~
好了,这篇文章就到这里,其实如果是一位java程序员应该对spring中AOP的使用蛮熟悉的,下一篇我会分享下在spring中如何实现这样的功能,下次再见~
本人菜鸡一只,如果有哪里写得不对,或者误导了大家的,请批评指出,本人一定虚心接受,坚决改正!
也提醒下自己:“骄傲在败坏以先,狂心在跌倒之前!”