Aspectj 实现Method条件运行

  最近我花了半个小时实现了一个Method的按自定义条件运行的pluginCondition-Run 。实现场景是由于我所工作的客户经常会是在同一个代码集上实现多个Brand,所以有些功能只会限制是几个brand调用,而其他的调用则不该调用。还有因为持续交互,我们会不停的release新的功能得到快速的反馈,在这前提下我们会经常遇见在我们刚开发完一个brand的产品代码,就要面临release,所以我们希望其不该对其他的brand产生影响。

  面对这样的需求初级程序员有些人肯定会觉得没什么了不起的啊,不就是几个if/else或者switch/case。我和我的团队对代码有一种天生的洁癖,对于太多复杂的if/elseswitch/case,以及将来会被移除的临时非产品代码分布在各处,有一种抵触心理。

对于有一定工作经验的程序员来说这样的需求肯定也不是什么问题,不就是AOP(面向切面编程),对,这就是我们所期望的解决方案,把处理的逻辑集中,和产品代码的分离。

知道了用AOP,也许你只对了一半,在AOP的世界里,有两种实现方式静态植入和动态代理,最早了AOP实现采用的是静态植入,然后由于IOC之类的框架的兴起,动态代理的实现方式也逐渐兴起,取代了静态植入的方式。但并不是说静态植入的方式就不再有用武之地的,在这里我们所采用的AOP框架Aspectj就是一个静态注入的框架,我们并没有和spring结合,动态代理的方式有个基本的问题就是你不能直接new这个对象这需要交给框架处理,如果是spring框架的话,这要求你必须是一个springbean,以及动态代理会有一些性能的损失。这对于该场景的限制太多,并不是我所期望的。

静态植入的框架在我以前的博客中也提到不少,如果感兴趣请移步 《IOC/AOP随笔目录》。在java世界里Aspectj.net世界里PostSharp(博客中静态植入原理分析篇《MSBuild + MSILInect实现编译时AOP之预览》)就是这类框架。

   回到主题,对于 condition-run如何使用请移步github文档

这里简述如何实现:

1 对于AOP第一步是匹配规则,所以定义一个标记:

@Retention(RUNTIME)

@Target({METHOD})

public @interface ConditionRun {

Class<? extends Runner> value();

}

 

其指向一个实现Runner接口的类型。

2:有了匹配规则,我们就可以找到切入点进行AOP逻辑的处理,

 

@Aspect

public class ConditionRunAspect {


@Around("methodsToBeConditionRun(conditionRun)")

public Object profile(ProceedingJoinPoint pjp, ConditionRun conditionRun) throws Throwable {

final Result result = isExec(pjp, conditionRun);

if (result.isExec()) {

return pjp.proceed();

}

return result.getDefaultValue();

}


private Result isExec(ProceedingJoinPoint pjp, ConditionRun conditionRun) {

try {

final Runner runner = conditionRun.value().newInstance();

final MethodSignature signature = (MethodSignature) pjp.getSignature();

return runner.exec(signature, pjp.getArgs());

} catch (Exception e) {

throw new RuntimeException("Runner must be empty constructor and make sure the config is ok.", e);

}

}


@Pointcut(value = "@annotation(conditionRun)")

public void methodsToBeConditionRun(ConditionRun conditionRun) {

}

}

 

  这里在切入方法调用之前,new了一个配置的Runner类型(注意必须午餐构造),并调用其exec方法获取是否运行该方法,如果不运行则返回什么默认值。

Runner runner = conditionRun.value().newInstance();

final MethodSignature signature = (MethodSignature) pjp.getSignature();

return runner.exec(signature, pjp.getArgs());

 

exec的参数签名为方法签名信息和方法运行时参数。

    一切都这么简单,现在你可以任意的框架Runner去做适合你的场景业务了。可以参照项目下得sample实例,该实例展示了一个当出入参数为3的时候执行,部位3则返回默认值1.

   想想还有那些场景,你是否遇见过某类单元测试我只希望运行在某种固定的场景下?假设在开发图形应用的时候,我们希望调用一些不同平台的特定api,虽然我们代码设计封装做得很好,但是我们希望有固定的集成测试去cover这部分逻辑,让我们的测试只运行是固定平台。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
AspectJ是一种基于Java语言的面向切面编程(AOP)的扩展。它通过在编译期间将切面代码织入到目标代码中,实现了对横切关注点的模块化和重用。 AspectJ实现原理主要包括以下几个步骤: 1. 编译器扩展:AspectJ通过扩展Java编译器,添加了对切面语法的支持。在编译Java源代码时,AspectJ编译器会解析切面文件中的切点和通知,并将其转换为字节码文件。 2. 切点匹配:AspectJ使用切点表达式来定义切点,切点表达式可以根据方法的签名、注解、访问修饰符等条件来匹配目标代码中的连接点。AspectJ编译器会根据切点表达式在目标代码中找到匹配的连接点。 3. 通知织入:一旦找到匹配的连接点,AspectJ会将切面中定义的通知代码织入到目标代码中。通知可以分为前置通知、后置通知、环绕通知等,它们会在目标代码执行前、后或者替代目标代码执行。 4. 字节码增强:AspectJ通过修改目标代码的字节码来实现通知的织入。它会在目标代码中插入切面代码,并调整字节码中的跳转指令,以确保通知的正确执行顺序。 5. 运行时支持:AspectJ还提供了运行时的支持,包括切面实例的创建和管理、连接点的动态绑定、通知的执行等。在程序运行时,AspectJ会根据切面的定义和连接点的匹配情况来决定是否执行通知。 总的来说,AspectJ通过编译器扩展和字节码增强的方式,将切面代码织入到目标代码中,实现了对横切关注点的模块化和重用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值