自己对AOP的理解笔记

本文介绍了AOP(面向切面编程)的概念,它用于减少代码冗余,提高程序的可维护性。通过一个游戏模板方法的例子展示了如何在每个子类的play方法中添加计时功能,以此说明AOP的重要性。然后,使用Java动态代理模式实现了AOP,动态地在游戏类的play方法前后添加时间计算逻辑,避免了在每个子类中手动添加代码。这体现了AOP的切面、连接点、增强和织入等核心概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

15. AOP

第一次听说AOP是在spring框架中听到的。

在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

看文字晦涩难懂,直接看个例子。

下面的这个是模板方法的实现。

TemplatePatternDemo,主类

public class TemplatePatternDemo {
	   public static void main(String[] args) {
	 
	      Game game = new Cricket();
	      game.play();
	      System.out.println();
	      game = new Football();
	      game.play();      
	   }
}

Game抽象类

其中,play方法的final很重要,防止了子类覆写此方法,打乱了执行顺序。

public abstract class Game {
	   abstract void initialize();
	   abstract void startPlay();
	   abstract void endPlay();
	 
	   //模板
	   public final void play(){
	 
	      //初始化游戏
	      initialize();
	 
	      //开始游戏
	      startPlay();
	 
	      //结束游戏
	      endPlay();
	   }
}

Cricket子类

public class Cricket extends Game {
	 
	   @Override
	   void endPlay() {
	      System.out.println("Cricket Game Finished!");
	   }
	 
	   @Override
	   void initialize() {
	      System.out.println("Cricket Game Initialized! Start playing.");
	   }
	 
	   @Override
	   void startPlay() {
	      System.out.println("Cricket Game Started. Enjoy the game!");
	   }
}

Football子类

public class Football extends Game {
	 
	   @Override
	   void endPlay() {
	      System.out.println("Football Game Finished!");
	   }
	 
	   @Override
	   void initialize() {
	      System.out.println("Football Game Initialized! Start playing.");
	   }
	 
	   @Override
	   void startPlay() {
	      System.out.println("Football Game Started. Enjoy the game!");
	   }
}

现在我要在每个球类的play()方法都要加一个计算玩了多久的功能。如果要实现可以每个paly()方法中再加一个计算时间的功能。这里只有两种球类运动,如果有更多的运动呢?那这个要每个都加,代码冗余。

我们如果把这个功能提取出来,用动态代理模式,完成这个功能的添加。这样就 减少了代码重复问题。这儿就是用动态代理模式实现了AOP。

康康怎么实现。

因为动态代理需要用接口实现。所以我这里在Game抽象类的上层加入了一个接口

public interface GameInterface {
    void initialize();
    void startPlay();
    void endPlay();

    //模板
    void play();
}

public abstract class Game implements GameInterface{


    //模板
    @Override
    public final void play(){

        //初始化游戏
        initialize();

        //开始游戏
        startPlay();

        //结束游戏
        endPlay();
    }
}
public class Cricket extends Game {

    @Override
    public void endPlay() {
        System.out.println("Cricket Game Finished!");
    }

    @Override
    public void initialize() {
        System.out.println("Cricket Game Initialized! Start playing.");
    }

    @Override
    public void startPlay() {
        System.out.println("Cricket Game Started. Enjoy the game!");
    }
}
public class Football extends Game {

    @Override
    public void endPlay() {
        System.out.println("Football Game Finished!");
    }

    @Override
    public void initialize() {
        System.out.println("Football Game Initialized! Start playing.");
    }

    @Override
    public void startPlay() {
        System.out.println("Football Game Started. Enjoy the game!");
    }
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

public class GameInovationHandler implements InvocationHandler {

    private GameInterface gameInterface ;

    public GameInovationHandler(GameInterface gameInterface){
        this.gameInterface = gameInterface;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println(System.currentTimeMillis()+"开始玩的");
        method.invoke(gameInterface,args);
        TimeUnit.SECONDS.sleep(2);
        System.out.println(System.currentTimeMillis()+"结束的");
        return null;
    }


}
public class TemplatePatternDemo {
    public static void main(String[] args) {

        GameInterface game = new Cricket();
        InvocationHandler gameInovationHandler = new GameInovationHandler(game);
        GameInterface gameProxy = (GameInterface) Proxy.newProxyInstance(game.getClass().getClassLoader(),
                game.getClass().getSuperclass().getInterfaces(), gameInovationHandler);
        gameProxy.play();

        System.out.println();
        game = new Football();
        gameInovationHandler = new GameInovationHandler(game);
        gameProxy = (GameInterface) Proxy.newProxyInstance(game.getClass().getClassLoader(),
                game.getClass().getSuperclass().getInterfaces(), gameInovationHandler);
        gameProxy.play();

    }
}

输出结果

1620121457799开始玩的
Cricket Game Initialized! Start playing.
Cricket Game Started. Enjoy the game!
Cricket Game Finished!
1620121459805结束的

1620121459805开始玩的
Football Game Initialized! Start playing.
Football Game Started. Enjoy the game!
Football Game Finished!
1620121461807结束的

以上就是用动态代理实现AOP的例子。

下面来康康名词。

切面:横切关注点,模块化后称为切面。个人理解是抽取出来的相同代码。比如上述invoke方法抽取出来的功能(记录时间)的代码。

连接点(Join point):程序执行过程中可被识别的某个点叫做连接点。就是有意义的代码。比如赋值操做,方法调用。

增强/通知(Advice):连接点处执行的逻辑叫增强。

上边的例子里是环绕增强。

 		//增强
		System.out.println(System.currentTimeMillis()+"开始玩的");
        method.invoke(gameInterface,args);
        TimeUnit.SECONDS.sleep(2);
        //增强
		System.out.println(System.currentTimeMillis()+"结束的");

切入点(Pointcut):某些特定连接点的逻辑叫做切入点。根据切入点我们可以判断哪些连接点需要增强。

织入(Weaving):把这些水平的切面连接到执行过程以组合成完整流程的行为称为织入。织入可以发生在编辑期,编译期,类加载期,运行期。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值