Gadtry-Aop, Spring Aop之外的新选择
Spring Aop之外的新选择Gadtry-Aop
作者: harbby(github) email: yezhixinghai@gmail.com 日期: 2018.12
简介
Gadtry 是一个构建于java8之上的工具库, 涵盖了Ioc
Aop
exec
graph
等等工具库,几乎涵盖了日常开发中非常多工具类,当然它还在不断丰富中.
Aop
在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。(来自百度百科)
Spring-Aop和Ioc组合可以说非常漂亮和完美, Spring-Aop中定义了非常好注解和概念,可以说是对Aop模式完美诠释,Spring体系本身也非常全面, 但是Spring体系过于庞大
, 且现实中我们有太多的非Spring项目.
Gadtry-Aop
Gadtry-Aop是 Gadtry 1.1版本开始加入全新功能,旨在降低Aop使用难度,同时尽量小巧简单, 提供在Spring-Aop之外的新选择.在依赖上除了字节码操作器javassist
外无任何依赖.
Gadtry-Aop 诞生有两个目的:
其一是非spring项目 也能尽量获得Spring-Aop相似Aop体验
其二: 我非常讨厌Spring-Aop 的expression 字符串表达式和一堆的注解.它难以记忆和阅读, Gadtry-Aop 为了简化使用采用了链式(函数式)Api设计,你只需参照下demo,然后借助ide就预览和使用所有功能,一切都是点点点
下载:
maven:
<dependency> <groupId>com.github.harbby</groupId> <artifactId>gadtry</artifactId> <version>1.1.0</version> </dependency>
非容器场景代理
这种场景非常多,就是你的项目中没有使用任何Ioc容器.
举个栗子:
T proxy = AopFactory.proxy(Class<T>) .byInstance(instance) .around(proxyContext -> { String name = proxyContext.getInfo().getName(); System.out.println(name); Object value = proxyContext.proceed(); switch (name) { case "add": Assert.assertEquals(true, value); //Set or List break; case "size": Assert.assertTrue(value instanceof Integer); break; } });
这个例子中 Class<T>
指类或接口, instance这个具体的实现类活子类实现类.这个例子中用到了 环绕通知(around)
模式. 这里注意如果Class<T>
是接口,则默认使用jdk动态代理, 否则使用字节码技术生成动态代理类.
我们在来看个结合Gadtry-Ioc容器例子
IocFactory iocFactory = GadTry.create(binder -> { binder.bind(Map.class).byCreator(HashMap::new).withSingle(); binder.bind(HashSet.class).by(HashSet.class).withSingle(); }).aop(binder -> { binder.bind("point1") .withPackage("com.github.harbby") //.subclassOf(Map.class) .classAnnotated() .classes(HashMap.class, HashSet.class) .whereMethod(methodInfo -> methodInfo.getName().startsWith("add")) .build() .before((info) -> { Assert.assertEquals("add", info.getName()); System.out.println("before1"); }) .after(() -> { Assert.assertTrue(true); System.out.println("after2"); }); }).initialize(); Set set = iocFactory.getInstance(HashSet.class);
这个例子中结合了Ioc容器来使用Aop, 在Spring开发中基本都是结合Ioc容器来使用的Aop的.
这个例子中我们 使用了扫包,过滤器等来定位需要被代理类和方法, 最后添加了 前置通知(before)
和后置通知(after)
基本概念
这篇文章中我们不会着重介绍IOC, 我们来重点感谢Aop的几个概念:
-
- Gadtry-Aop支持通知类型
-
前置通知(Before) 指: 在目标方法被调用之前调用通知功能。
-
后置通知(After)指: 在目标方法完成之后调用通知,无论方法正确执行与否。
-
返回通知 (after-Returning) 指: 在目标方法成功执行之后调用通知。
-
异常通知(After-throwing):在目标方法抛出异常后调用通知。
-
环绕通知(Around):通知包裹了被通知的方法,由使用者决定和调用目标方法
*** 关于通知类型须知: **
()->{} ,切入逻辑中无法获取目标方法相关信息,如args[]名称等 (info)->{info.getArgs()} , 这样就可以获取目标方法相关信息
-
切点(pointcut)
组成切面的最小单位, 我们通常使用明确的类和方法名称,或是利用扫描和过滤所匹配的类和方法名称来指定切点.
切点定义:
binder.bind("point1") .withPackage("com.github.harbby") //.subclassOf(Map.class) .classAnnotated() .classes(HashMap.class, HashSet.class) .whereMethod(methodInfo -> methodInfo.getName().startsWith("add")) .build() .before((info) -> { Assert.assertEquals("add", info.getName()); System.out.println("before1"); }) .after(() -> { Assert.assertTrue(true); System.out.println("after2"); });
-
切面(pointcut)
切面用来组织一组相关的切点.一个切面中可以定义多个切点
public class DemoAspect implements Aspect { @Override public void register(Binder binder) { binder.bind("point1") .classes(HashSet.class).build() .after(() -> { System.out.println("after"); }); binder.bind("point2") .classes(Map.class).build() .after(() -> { System.out.println("after"); }); } }
-
动态代理
Gadtry-Aop 优先使用jdk动态代理,如果遇到非接口无法代理时则使用Javassist动态字节码技术来代理
过滤器
在Aop中,我们通常需要指出哪些些类中的哪些些方法需要被代理拦截,Spring-Aop通过中通过expression表达式描述具体被代理的类和方法. 在Gadtry-Aop中我们细化成 类过滤
和方法过滤
,并使用简易函数式Api来表达.
-
扫描型-类过滤
-
withPackage(String packageName): 包过滤, 匹配此包下的所有类
-
subclassOf(Class<?>... subclasses): 匹配此类的子类型(包括本身类型)
-
classAnnotated(Class<? extends Annotation>... classAnnotations): 带有此注解的类
-
whereClass((classInfo)-> classInfo.getName().endsWith("impl")): 更灵活的class过滤,如按名称过滤
-
-
明确型-类过滤
注意和上面扫描可同时生效 为 or 的关系
推荐使用此方式. 大部分场景下需要被代理的类或接口都是可以确定下来的,使用扫描往往带来潜在未知风险
-
classes(HashMap.class, HashSet.class): 如明确只代理HashMap和HashSet两个类(不涵子类)实例
-
-
方法过滤
在通过上面两种方式找出需要被代理的类后, 后需要在最后进行代理方法过滤.
-
returnType(Class<?>... returnTypes): 匹配返回值是此类的子类型(包括本身类型)的方法
-
methodAnnotated(Class<? extends Annotation>... methodAnnotations):带有此注解的方法
-
whereMethod(methodInfo -> methodInfo.getName().startsWith("add")): 更加灵活的方法过滤,如:此处匹配出名称为add开头的方法
-
最后
Spring-Aop太权威了,您可能无权对它做出任何改变,但是Gadtry-Aop才刚诞生不久, 如果您对Aop有什么自己的见解和想法欢迎一起来讨论和完善, 我们的地址是: https://gitee.com/mirrors/Gadtry 欢迎您的访问,里面还有更多精彩!

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
#自动化测试框架的4种有效分类与使用选择
前言 有人喜欢创造世界,他们做了开发者;有的人喜欢开发者,他们做了测试员。什么是软件测试?软件测试就是一场本该在用户面前发生的灾难提前在自己面前发生了,这会让他们生出一种救世主的感觉,拯救了用户,也就拯救者这个软件,避免了他们被卸载的命运。 自动化测试一直是敏捷开发和敏捷测试的重要基石,也是DevOps和CI/CD必不可少的组成部分。由于不同项目的测试需求不同,以及各种不同的限制,导致需要的自动化测试框架和工具也不同。比如很多金融和能源类的企业就倾向于选择收费的企业级自动化测试框架或者工具,而新型互联网企业则倾向于开源免费的自动化测试框架或者工具,或者基于它们进行二次定制开发,或者重新开发适合自己的自动化测试框架、工具或者平台。 之前一篇文章——《自动化测试框架Cucumber和RobotFramework的实战对比》仅仅针对两种自动化测试框架进行了讨论,却引发了大量的讨论,由此可见业界对于自动化测试框架存在很多不同的理解和争议。在我看来,没有任何一个自动化测试框架是银弹,并且适合所有类型的测试,所以“如何选择一款适合自己的测试框架”变成为了一个首要问题。我将自动化测试进行了简单的分...
- 下一篇
CSDN文章自动展开全文无需登录插件(仅限Chrome)!
众所周知csdn里所有blog都记录了程序员们多年的技术积累,他们不吝啬技术,免费分享经验,随着资料的丰富,那些踩过的坑,报过的错,全被前人当成树种下了,现在各类问题基本都能在网上得到解决方案。而csdn却拿着这些资源当王牌,限制行内人士自由,连看文章都需要登录(如果你是作者,没有登录的话,可能连你自己的文章都看不了!)。早年csdn在国内基本一家独大,有些大牛们的blog也在csdn,没有别的选择。但是现在大牛们都有了自己的blog,或者有些已经不更新了,同时随着osc的日益壮大,导致csdn流量暴跌,他们试图以登录的方式来挽回损失的流量,搞了这么一出,登录才能看全文,简直恶心至极!! 对于csdn这种暴力行为,作为码农第一反应当然是拒绝的,我就想安安静静看个文章,你让我手动展开全文就算了(根本不知道你们加这个功能到底干啥,跟风好玩?),最主要还要求我登录,真是觉得手握资源就可以为所欲为?既然你这样,就不要怪我那样。 csdn文章内容其实在一开始就加载完了,只是设置了height和overflow把一部分隐藏起来了,想要自动展开全文只需要把这两个去掉就行了,用chrome或者...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Red5直播服务器,属于Java语言的直播服务器
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- CentOS关闭SELinux安全模块
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- SpringBoot2整合Redis,开启缓存,提高访问速度
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- CentOS7安装Docker,走上虚拟化容器引擎之路