JAVA轻量级高性能AOP框架 ----- gordian

1. 简介

1.1 项目地址

1.2为什么造这个轮子

博主太闲了

现在的spring aop 已经非常的完善了,但是却有以下几个小缺点

  • 当引入了太多第三方jar 后,Pointcut 的定义被分散到了不同的 jar, 你可能不知道在你的业务方法在执行之前会去执行多少方法,这些方法都会干什么。比如@Transactional 注解,大家都知道他的原理就是 aop,那么我想看看里面他会在我方法执行前,执行后做了什么,就需要去翻文档才能知道他执行aop的类在哪里,这算不错的体验了,那如果是你接手了一个古老且没有文档的业务代码,各种aop的定义分散在各处,那么确实是一场噩梦,会有很多隐藏的代码在你不知道的地方默默工作着。
  • 如果我想在非spring 项目里去使用aop,确实有很多第三方优秀的aop框架,但是很多都是基于动态代理 实现的,那么使用起来将会对你的业务代码带来一部分的入侵 , 如下所示。
A a = new A();
a.exec();

//动态代理
A a = proxy();
a.exec();

gordian 就是为了解决以上两个问题而存在的, 同时因为是在编译期去生成代理代码,性能将会比动态代理 更高

1.3 为什么叫 gordian

其实这个名字来源于 gordian worm , 也是我们常说的 铁线虫 了,他会入侵螳螂 体内,然后完全控制 螳螂 的行为,其实这和我这个框架类似,他将在编译期的时候入侵业务代码,以至于改变这个方法行为

2. 使用

github 中下载 源码后执行 , 传送门

mvn clean install

然后在项目里引入

		<dependency>
            <groupId>com.chy</groupId>
            <artifactId>gordian</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

包中提供了一个接口 Gordian, 新建一个类去实现这个接口, 在实现方法中,可以尽情的写方法执行前,以及方法执行后的逻辑,parasitifer.exec() 代表你业务逻辑要执行的方法

public class GordianImp implements Gordian {
   
    @Override
    public Object control(Parasitifer parasitifer)  throws Throwable {
        System.out.println("GordianImp 执行开始 @@@@@@@@@@@@@@ --->");
        Object result = parasitifer.exec();
        System.out.println("GordianImp 执行结束 ################");
        return result;
    }
}

然后在你你要切入的方法的地方打上 @Parasitic注解,并且指定你刚刚写的 Gordian 的实现类

public class Chy {
    
    @Parasitic(gordians = {GordianImp.class})
    public void test() {
        System.out.println("执行了 test 方法");
    }
    
}

最后直接去 new 出这个类,调用即可

 public static void main(String[] args) throws InterruptedException {
        Chy chy = new Chy();
        chy.test();
    }

执行后可以看到

在这里插入图片描述

2.1 . 多个 Gordian

仔细的读者可以看出来,@Parasitic(gordians = {GordianImp.class}) 注解中传入的 gordians 是一个数组,那么传入的时候,排在右边的Gordian 将会套在外层

@Parasitic(gordians = {GordianImp.class, GordianImp2.class})
    public void test() throws InterruptedException {
        System.out.println("执行了-----test");
    }

在这里插入图片描述

3. 实现原理

lombok 一样,gordian 将在代码的编译期 就去生成了对应的 代理代码

还是上面test() 那个列子,打开编译后的class文件可以看到生成的代码如下所示 , 为了方便注释,博主将代码复制下来

public class Chy {
    public Chy() {
    }

    public void test() throws InterruptedException {
        //将业务代码复制到了 lambda 表达式中
        Parasitifer chyParasitifer_0 = () -> {
            System.out.println("执行了-----test");
            return null;
        };
        //把注解上面指定的实现类给 new了
        GordianImp gordianVar_0 = new GordianImp();

        try {
   	        //执行了 Lambda 中的代码
            gordianVar_0.control(chyParasitifer_0);
        } catch (Throwable var4) {
            if (var4 instanceof InterruptedException) {
                throw (InterruptedException)var4;
            } else {
                throw (RuntimeException)var4;
            }
        }
    }
}

是不是一看上面代码就一目了然了

4. 工厂模式

如果细心的读者看了上面生成的代码,可能会有一个小问题, Gordian 的实现类每次执行方法的时候都会去 new 一个新的对象,那么如何去让多个业务方法公用一个 Gordian 实现类嗯?

所以这里提供了工厂模式

将注解 @Parasitic 中的参数 factoryMode = true 即可

public class GordianImp2 implements Gordian {
    Integer i = 0;
    @Override
    public Object control(Parasitifer parasitifer) throws Throwable {
        System.out.println("GordianImp2 执行开始 @@@@@@@@@@@@@@ --->" + i);
        Object result = parasitifer.exec();
        i++;
        System.out.println("GordianImp2 执行结束 ################");
        return result;
    }
}

这里定义一个新的 GordianImp , 里面有个 i 每次调用都会 自加

然后调用 test() , test2() 方法

public class Chy {

    @Parasitic(gordians = {GordianImp2.class}, factoryMode = true)
    public void test() throws InterruptedException {
        System.out.println("执行了-----test");
    }

    @Parasitic(gordians = {GordianImp2.class}, factoryMode = true)
    public void test2() throws InterruptedException {
        System.out.println("执行了-----test2");
    }

    public static void main(String[] args) throws InterruptedException {
        Chy chy = new Chy();
        chy.test();
        chy.test2();
        chy.test();
    }
    
}

在这里插入图片描述

4.1 自定义工厂

这里工厂是可以让使用者自定义的,你可以花式去创建Gordian 的实现对象

使用 SPI机制 来让你自定义工厂:
META-INF.services 文件夹下添加 com.chy.gordian.factory.GordianFactory 文件,里面写入你工厂实现类的全路径即可,哦对了自定义的工厂需要实现接口 GordianFactory, 然后重写里面的 public Gordian createInstance(String gordianName) 方法, 入参的string 将是 Gordian 实现类的类全路径

还有一个 order() 方法用来指定加载工厂的优先级,数字越小优先级越高。

4.1.1 spring的支持

所以你可以通过上面提到的自定义工厂机制来把 GordianImp 交给 spring 管理,这样你就可以在 GordianImp 上打上@Component 注解拥有spring 给与的一切能力, 笔者这久比较忙后面会支持这个功能

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值