Respect给到贝壳、闲鱼、AspectJ.
相关github链接在文章最后[参考资料]处
开门见山
先来说说如何配置,再概括实现原理,后续再看情况出原理解析。
添加配置,这里添加的是贝壳开源的beike_aspectd,项目不需支持空安全则把null-safety去掉
beike_aspectd:
git:
url: https://github.com/LianjiaTech/Beike_AspectD.git
ref: null-safety/2.5.3
在与pubspec.yaml同级目录下添加aop_config.yaml配置文件文件内容
flutter_tools_hook:
- project_name: 'beike_aspectd'
exec_path: 'bin/starter.snapshot'
由于需要修改到引擎源码,因此需要到Flutter sdk下添加开源库的flutter_tools.patch补丁。
github连接 将inner/flutter_tools.patch下载下来,打入到Flutter sdk中
#cd到flutter sdk 中 flutter_tools所在路径
MacBook-Pro-3:flutter_tools hbb$ pwd
/Users/hbb/lib/flutter/packages/flutter_tools
#打上补丁 /Users/hbb/AndroidStudioProject替换为你自己的项目路径
MacBook-Pro-3:flutter_tools hbb$ git apply /Users/hbb/AndroidStudioProjects/Beike_AspectD/inner/flutter_tools.patch
#此时需要删除bin/cache/flutter_tools.stamp文件
# 重新build
MacBook-Pro-3:flutter_tools hbb$ flutter packages get
Building flutter tool...
Running "flutter pub get" in flutter_tools... 1,382ms
编写get方法和hook相关代码,创建aop_impl.dart。这里做演示,只演示hook方法。
更多用法请查看参考资料的源码链接中的README.md。
import 'package:beike_aspectd/aspectd.dart';
@Aspect()
@pragma("vm:entry-point")
class CallDemo {
@pragma("vm:entry-point")
CallDemo();
//实例方法,我的项目名为channel_demo,@Call(文件名,类名,-方法名)
@Call("package:channel_demo/main.dart", "_MyHomePageState", "-_incrementCounter")
@pragma("vm:entry-point")
void _incrementCounter4(PointCut pointcut) {
print('[beike_aspectd]: call instance method2!');
pointcut.proceed();
}
}
在你自己项目的main.dart中import。
添加ignore: unused_import避免被编译器tree shake优化掉。
// ignore: unused_import
import 'package:channel_demo/aop_impl.dart';
注:目前仅支持的Flutter版本为1.22.4 2.2.2 2.5.3。
切换到对应版本的Flutter SDK即可
运行代码,以下打印代码Aop成功注入
最终运行效果
至此,结束
原理概括
这里借用aspectd的原理图
一句话概括:编译时替换产物
恩,好像可以为所欲为了~