AspectD: An Effective AOP Solution for Flutter — Open Sourced by Alibaba Xianyu Tech Team

Background

AspectD: Dart-Oriented AOP Framework

Design Details

Typical AOP Scenarios

aop.dartimport 'package:example/main.dart' as app;
import 'aop_impl.dart';
void main()=> app.main();aop_impl.dartimport 'package:aspectd/aspectd.dart';@Aspect()
@pragma("vm:entry-point")
class ExecuteDemo {
@pragma("vm:entry-point")
ExecuteDemo();
@Execute("package:example/main.dart", "_MyHomePageState", "-_incrementCounter")
@pragma("vm:entry-point")
void _incrementCounter(PointCut pointcut) {
pointcut.proceed();
print('KWLM called!') ;
}
}

Developer-Oriented API design

Design of PointCut

@Call("package:app/calculator.dart","Calculator","-getCurTime")
@pragma('vm:entry-point')
class PointCut {
final Map<dynamic> sourceInfos;
final Object target;
final String function;
final String stubId;
final List<dynamic> positionalParams;
final Map<dynamic, dynamic> namedParams;
@pragma('vm:entry-point')
PointCut(this.sourceInfos, this.target, this.function, this.stubId,this.positionalParams, this.namedParams);
@pragma('vm:entry-point')
Object proceed(){
return null;
}
}

Design of Advice

@pragma("vm:entry-point")
Future<String> getCurTime(PointCut pointcut) async{
...
return result;
}

Design of Aspect

@Aspect()
@pragma("vm:entry-point")
class ExecuteDemo {
@pragma("vm:entry-point")
ExecuteDemo();
...
}

Compilation of AOP code

Contain the Main Entry in the Original Project

Compilation in Debug Mode

Compilation in Release Mode

Dill Operation

Structure of Dill

dart bin/dump_kernel.dart /Users/kylewong/Codes/AOP/aspectd/example/aop/build/app.dill /Users/kylewong/Codes/AOP/aspectd/example/aop/build/app.dill.txt

Transformation of Dill

@override
MethodInvocation visitMethodInvocation(MethodInvocation methodInvocation) {
methodInvocation.transformChildren(this);
Node node = methodInvocation.interfaceTargetReference?.node;
String uniqueKeyForMethod = null;
if (node is Procedure) {
Procedure procedure = node;
Class cls = procedure.parent as Class;
String procedureImportUri = cls.reference.canonicalName.parent.name;
uniqueKeyForMethod = AspectdItemInfo.uniqueKeyForMethod(
procedureImportUri, cls.name, methodInvocation.name.name, false, null);
}
else if(node == null) {
String importUri = methodInvocation?.interfaceTargetReference?.canonicalName?.reference?.canonicalName?.nonRootTop?.name;
String clsName = methodInvocation?.interfaceTargetReference?.canonicalName?.parent?.parent?.name;
String methodName = methodInvocation?.interfaceTargetReference?.canonicalName?.name;
uniqueKeyForMethod = AspectdItemInfo.uniqueKeyForMethod(
importUri, clsName, methodName, false, null);
}
if(uniqueKeyForMethod ! = null) {
AspectdItemInfo aspectdItemInfo = _aspectdInfoMap[uniqueKeyForMethod];
if (aspectdItemInfo?.mode == AspectdMode.Call &&
! _transformedInvocationSet.contains(methodInvocation) && AspectdUtils.checkIfSkipAOP(aspectdItemInfo, _curLibrary) == false) {
return transformInstanceMethodInvocation(
methodInvocation, aspectdItemInfo);
}
}
return methodInvocation;
}

Syntax Supported by AspectD

Call

import 'package:aspectd/aspectd.dart';@Aspect()
@pragma("vm:entry-point")
class CallDemo{
@Call("package:app/calculator.dart","Calculator","-getCurTime")
@pragma("vm:entry-point")
Future<String> getCurTime(PointCut pointcut) async{
print('Aspectd:KWLM02');
print('${pointcut.sourceInfos.toString()}');
Future<String> result = pointcut.proceed();
String test = await result;
print('Aspectd:KWLM03');
print('${test}');
return result;
}
}

Execute

import 'package:aspectd/aspectd.dart';@Aspect()
@pragma("vm:entry-point")
class ExecuteDemo{
@Execute("package:app/calculator.dart","Calculator","-getCurTime")
@pragma("vm:entry-point")
Future<String> getCurTime(PointCut pointcut) async{
print('Aspectd:KWLM12');
print('${pointcut.sourceInfos.toString()}');
Future<String> result = pointcut.proceed();
String test = await result;
print('Aspectd:KWLM13');
print('${test}');
return result;
}

Inject

@override
Widget build(BuildContext context) {
final Map<TapGestureRecognizer> gestures = <Type, GestureRecognizerFactory>{};
if (onTapDown ! = null || onTapUp ! = null || onTap ! = null || onTapCancel ! = null) {
gestures[TapGestureRecognizer] = GestureRecognizerFactoryWithHandlers<TapGestureRecognizer>(
() => TapGestureRecognizer(debugOwner: this),
(TapGestureRecognizer instance) {
instance
..onTapDown = onTapDown
..onTapUp = onTapUp
..onTap = onTap
..onTapCancel = onTapCancel;
},
);
}
import 'package:aspectd/aspectd.dart';@Aspect()
@pragma("vm:entry-point")
class InjectDemo{
@Inject("package:flutter/src/widgets/gesture_detector.dart","GestureDetector","-build", lineNum:452)
@pragma("vm:entry-point")
static void onTapBuild() {
Object instance; //Aspectd Ignore
Object context; //Aspectd Ignore
print(instance);
print(context);
print('Aspectd:KWLM25');
}
}

Build Process Support

kylewong@KyleWongdeMacBook-Pro fluttermaster % git apply --3way /Users/kylewong/Codes/AOP/aspectd/0001-aspectd.patch
kylewong@KyleWongdeMacBook-Pro fluttermaster % rm bin/cache/flutter_tools.stamp
kylewong@KyleWongdeMacBook-Pro fluttermaster % flutter doctor -v
Building flutter tool...

Practice and Consideration

Conclusion

Original Source

--

--

--

Follow me to keep abreast with the latest technology news, industry insights, and developer trends. Alibaba Cloud website:https://www.alibabacloud.com

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Build Your Own Blog Portfolio with Web Components: The Basics

How Docker reduces development costs?

KillApps PRO MOD APK 1.24.3 (Unlocked)

KillApps PRO MOD APK 1.24.3 (Unlocked)

Building Meshes in Unity, Vertex by Vertex

How to extend an Azure DevOps YAML Pipeline Template

How to password protect AWS Elasticsearch’s Kibana

How To Select a Tool For Continuous API Testing

01coin Project Update: January 1, 2018

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Alibaba Cloud

Alibaba Cloud

Follow me to keep abreast with the latest technology news, industry insights, and developer trends. Alibaba Cloud website:https://www.alibabacloud.com

More from Medium

Mobile Device Management Guide 2022: AOSP for custom MDM

Polymorphism | OOP Concepts 1/4.

What’s New in Appwrite’s Storage

Properly Setting up a Scheduled Cloud Function in Firebase