实现简单的AOP前置后置增强

AOP操作是我们日常开发经常使用到的操作,例如都会用到的spring事务管理.今天我们通过一个demo实现对一个类的某一个方法进行前置和后置的增强.

//被增强类
public class PetStoreService {
    //被增强方法
    public void placeOrder(){
        System.out.println("place order");
    }
}
//增强类
public class TransactionManager {

    //前置方法
    public void start() {
        System.out.println("start");
    }

    //后置方法
    public void end() {
        System.out.println("end");
    }
}

我们要做的就是在PetStoreService 中的placeOrder()执行前和执行后分别执行TransactionManager 中的start()和end()方法.下面我们将抽象出一个通知接口

//通知
public interface Advice {
    //执行增强方法
    public void invoke(InterceptorChain chain);
}

两个实现类,分别来执行start()和end()方法

//前置增强
public class BeforeAdvice implements Advice {
    //增强方法所属实例对象
    private Object object;
    //增强方法
    private Method method;
    //增强方法的参数
    private Object[] arguments;

    public BeforeAdvice(Object object, Method method, Object[] arguments) {
        this.object = object;
        this.method = method;
        this.arguments = arguments;
    }

    //织入方法
    public void invoke(InterceptorChain chain) {
        try {
            //执行增强方法
            method.invoke(object, arguments);
            //返回
            chain.proceed();
        } catch (Exception e) {
            System.out.println("执行after方法失败!!!!");
        }
    }
}
//后置增强
public class AfterAdvice implements Advice {
    //增强方法所属实例对象
    private Object object;
    //增强方法
    private Method method;
    //增强方法的参数
    private Object[] arguments;

    public AfterAdvice(Object object, Method method, Object[] arguments) {
        this.object = object;
        this.method = method;
        this.arguments = arguments;
    }

    //织入方法
    public void invoke(InterceptorChain chain) {
        try {
            //返回
            chain.proceed();
            //执行增强方法
            method.invoke(object, arguments);
        } catch (Exception e) {
            System.out.println("执行after方法失败!!!!");
        }
    }
}

两个方法中的构造子相同,都是给出通知类所需要的参数,而invoke()则是使用反射执行增强方法.

需要注意的是invoke()方法的参数,是一个拦截器链,两个方法都在执行自身Method方法前或者后执行了拦截器链中的方法.

下面是拦截器链

public class InterceptorChain {

    //拦截器链
    private List<Advice> adviceList;

    //需要增强的对象
    private Object object;

    //需要增强的方法
    private Method method;

    //当前需要执行方法的参数
    private Object[] arguments;

    //当前要执行的拦截器指针
    private int pointer = -1;

    //构造子
    InterceptorChain(Object obj, Method method, Object[] arguments) {
        this.object = obj;
        this.method = method;
        this.arguments = arguments;
        this.adviceList = new ArrayList<Advice>();
    }

    //执行拦截器链
    public void proceed() {
        //如果当前指针指向拦截器末尾则执行自身得方法
        if (this.pointer == adviceList.size() - 1) {
            invoke();
            return;
        }

        //指针+1
        pointer++;

        //获取需要执行的拦截器
        Advice advice = this.adviceList.get(pointer);

        //执行了拦截器
        advice.invoke(this);
    }

    //执行原方法
    public void invoke() {
        try {
            method.invoke(object, arguments);
        } catch (Exception e) {
            System.out.println("执行原有方法失败!!!");
        }
    }

    //增加拦截器

    public void addAdvice(Advice advice) {
        this.adviceList.add(advice);
    }
}

这是一个核心类,其中的关键在于,客户端将把增强类添加到拦截器链中,在拦截器链中有一个指针pointer用来指向即将执行的增强方法.

下面是客户端调用

public class Main {
    public static void main(String[] args) throws Exception {
        //需要增强的对象
        PetStoreService petStoreService = new PetStoreService();
        //增强
        TransactionManager transactionManager = new TransactionManager();

        //创建拦截器
        InterceptorChain interceptorChain = new InterceptorChain(petStoreService, PetStoreService.class.getMethod("placeOrder"), new Object[0]);

        //增加拦截器链
        interceptorChain.addAdvice(new BeforeAdvice(transactionManager, TransactionManager.class.getMethod("start"), new Object[0]));

        //增加拦截器链
        interceptorChain.addAdvice(new AfterAdvice(transactionManager, TransactionManager.class.getMethod("end"), new Object[0]));

        //执行拦截器方法
        interceptorChain.proceed();
    }
}

我们分别创建需要增强的对象,还有增强对象.并把增强对象中的增强方法添加到拦截器链中.最终我们实现了,按照顺序执行完了拦截器链中的方法.感兴趣的同学可以debug试试看.

两个advice中调用拦截器的proceed()方法顺序,不一样的话,会有不同的结果哦.

原文地址:https://www.cnblogs.com/zumengjie/p/11335455.html

时间: 2024-11-15 07:24:53

实现简单的AOP前置后置增强的相关文章

spring AOP 前置增强,后置增强小Demo

服务员接口 Waiter.java package com.paic.zhangqi.spring.aop; public interface Waiter { void greetTo(String name); void serveTo(String name); } 服务员接口实现类 NaiveWaiter.java package com.paic.zhangqi.spring.aop; public class NaiveWaiter implements Waiter { @Over

Spring aop——前置增强和后置增强 使用注解Aspect和非侵入式配置

AspectJ是一个面向切面的框架,它扩展了java语言,定义了AOP语法,能够在编译期提供代码的织入,所以它有一个专门的编译器用来生成遵守字节码字节编码规范的Class文件 确保使用jdk为5.0以上版本. 01.使用注解标注增强(AspectJ)  :取代了配置文件中的aop:pointcut节点的配置 添加jar和log4j的配置文件 aspectj-1.8.7.jar aspectjweaver.jar 添加头文件: xmlns:aop="http://www.springframewo

前置后置自增自减操作

class Int { friend ostream& operator<<(ostream& os, const Int& i); friend istream& operator>>(istream& is, Int& i); friend bool operator<(const Int& a, const Int& b); private: int value; public: Int():value(0

前置后置单目运算符重载函数返回值用法

Clock& Clock::operator ++() //前置单目运算符重载函数{Second++;if(Second>=60){Second=Second-60;Minute++;if(Minute>=60){Minute=Minute-60;Hour++;Hour=Hour%24;}}return *this;}//后置单目运算符重载Clock Clock::operator ++(int) //注意形参表中的整型参数{Clock old=*this;++(*this);retu

vue路由导航守卫及前置后置钩子函数参数详解

首先构建一个测试demo如下图: 接着来探讨路由配置界面 import Vue from 'vue' import Router from 'vue-router' // import HelloWorld from '@/components/HelloWorld' Vue.use(Router) const router = new Router({ routes: [{ path: '/', name: 'HelloWorld', component: resolve => require

C: printf参数执行顺序与前置后置自增自减的影响

起源: 今天在了解副作用side-effect的过程中,看到了下面的网页,把我带到了由printf引起的一系列问题,纠结了一整天,勉强弄懂. 第一个代码没什么好解释的.而第二个printf("return of swap is %d\tx=%d,y=%d\n",swap(&x,&y),x,y)居然是"return of swap is 1 x=1,y=0",输出的x和y的值并没有改变! 原因在于C语言函数参数的处理是从右到左的压栈顺序(这个我在看第一

前置操作符 后置操作符

++操作符的重载 1.全局函数和成员函数都可以进行重载. 2.前置++操作符不需要参数. 3.后置++操作符需要int类型的占位参数(区分前置后置). #include <iostream> #include <string> using namespace std; class Test { int mValue; public: Test(int i) { mValue = i; } int value() { return mValue; } Test& operat

自己实现简单的AOP(一)简介

AOP 和 OOP,在我看来是两种相辅相成的技术,作为OOP的补充,AOP 有着自己特殊的应用场景. 假设,我们需要在Service层实现以下几项基本功能: /// <para>1.自动管理数据库连接[可选]</para> /// <para>2.自动管理数据库事务,当接收到异常后(无论什么异常)事务将自动回滚[可选]</para> /// <para>3.服务级加锁[必选]</para> /// <para>4.以统一方

Spring入门篇7 ---- 简单介绍AOP

Spring-AOP 面向切面编程,它是对OOP的一种补充,OOP一般就是纵向关系,举个例子我们发一个用户信息的请求,正常情况下流程就是:身份验证 ——查询用户信息——日志记录(是情况而定)——返回信息,这个就是OOP面向对象编程,但如果有很多业务的话,那么身份验证,日志处理(一般AOP不会用于业务日志处理,否则以后运维的时候比较麻烦),会被调用很多次,这个时候可以引入AOP,他是面向切片处理,它会将程序横向截断,例如把权限模块进行抽离,实现解耦,如果后续权限需要调整只需要调整抽离出来的权限组件