Personal blog
www.milovetingting.cn
Simple implementation of Android buried point scheme – AspectJ of AOP
The definition of AOP
AOP for the abbreviation of Aspect Oriented Programming, meaning: section-oriented Programming, through pre-compilation and runtime dynamic proxy to achieve unified maintenance of program functions of a technology.
The above definition of AOP is quoted from Baidu Encyclopedia.
AOP application scenarios
Logs, performance statistics, permission control, and buried points
There are many concrete implementation schemes of AOP, and AspectJ is chosen to achieve it simply
- Listen to the View click, the page open and close
- Add start and end logs for methods
- Statistics method run time
The use of AspectJ
The introduction of the AspectJ
AspectJX, an AOP framework based on AspectJ, is referenced here
Create an Android project and add dependencies to the build.gradle file in the root directory of the project
dependencies {
/ /...
classpath 'com. Hujiang. Aspectjx: gradle - android plugin - aspectjx: mid-atlantic moved'
/ /...
}
Copy the code
Create a new Module, select Android Library as the type, and add the corresponding dependencies to the build.gradle file of the new Library
apply plugin: 'android-aspectjx'
Copy the code
Add a reference to the library you just created and a dependency on AspectJ to your app’s build.gradle file
apply plugin: 'android-aspectjx'
dependencies {
/ /...
implementation project(':library')}Copy the code
Listen to the View click, the page open and close
Create a new callback interface in the Library, TrackCallBack
public interface TrackCallBack {
/** * when View is clicked **@param pageName
* @param viewIdName
*/
void onClick(String pageName, String viewIdName);
/** ** when the page opens **@param pageName
*/
void onPageOpen(String pageName);
/** ** when the page is closed **@param pageName
*/
void onPageClose(String pageName);
}
Copy the code
Create a pointcut TrackPoint in the Library
public class TrackPoint {
private static TrackCallBack mTrackCallBack;
private TrackPoint(a) {}/** * initialize *@param trackCallBack
*/
public static void init(TrackCallBack trackCallBack) {
mTrackCallBack = trackCallBack;
}
static void onClick(String pageName, String viewIdName) {
if (mTrackCallBack == null) {
return;
}
mTrackCallBack.onClick(pageName, viewIdName);
}
static void onPageOpen(String pageName) {
if (mTrackCallBack == null) {
return;
}
mTrackCallBack.onPageOpen(pageName);
}
static void onPageClose(String pageName) {
if (mTrackCallBack == null) {
return; } mTrackCallBack.onPageClose(pageName); }}Copy the code
Create a new section TraceAspect in the library
@Aspect
public class TraceAspect {
private static final String TAG = TraceAspect.class.getSimpleName();
@Pointcut("execution(* onClick(..) )")
public void onClickPointcut(a) {}@Pointcut("execution(* android.app.Activity+.onCreate(..) )")
public void activityOnCreatePointcut(a) {}@Pointcut("execution(* android.app.Activity+.onDestroy(..) )")
public void activityDestroyPointcut(a) {}@Around("onClickPointcut()")
public void onClick(ProceedingJoinPoint joinPoint) throws Throwable {
Object target = joinPoint.getTarget();
String className = "";
if(target ! =null) {
className = target.getClass().getName();
}
Object[] args = joinPoint.getArgs();
if (args.length > 0 && args[0] instanceof View) {
View view = (View) args[0];
String entryName = view.getResources().getResourceEntryName(view.getId());
TrackPoint.onClick(className, entryName);
}
joinPoint.proceed();
}
@Around("activityOnCreatePointcut()")
public void pageOpen(ProceedingJoinPoint joinPoint) throws Throwable {
Object target = joinPoint.getTarget();
String className = target.getClass().getName();
TrackPoint.onPageOpen(className);
joinPoint.proceed();
}
@Around("activityDestroyPointcut()")
public void pageClose(ProceedingJoinPoint joinPoint) throws Throwable { Object target = joinPoint.getTarget(); String className = target.getClass().getName(); TrackPoint.onPageClose(className); joinPoint.proceed(); }}Copy the code
Create a new Application in the app module and initialize it in onCreate:
public class App extends Application {
private static final String TAG = TraceAspect.class.getSimpleName();
@Override
public void onCreate(a) {
super.onCreate();
TrackPoint.init(new TrackCallBack() {
@Override
public void onClick(String pageName, String viewIdName) {
Log.d(TAG, "onClick:" + pageName + "-" + viewIdName);
// Execute the corresponding business
}
@Override
public void onPageOpen(String pageName) {
Log.d(TAG, "onPageOpen:" + pageName);
// Execute the corresponding business
}
@Override
public void onPageClose(String pageName) {
Log.d(TAG, "onPageClose:" + pageName);
// Execute the corresponding business}}); }}Copy the code
New applications need to be referenced in AndroidManifest to take effect.
After running the App, click to open another Activity, and then exit the Activity one by one. The output log is as follows:
The 2020-01-13 16:50:17. 373, 16610-16610 / com. Wangyz. Aspectjdemo D/TraceAspect: OnPageOpen: com. Wangyz. Aspectjdemo. MainActivity 16:50:19. 2020-01-13, 243, 16610-16610 / com. Wangyz. Aspectjdemo D/TraceAspect: OnClick: com. Wangyz. Aspectjdemo. MainActivity - btn_open 16:50:19 2020-01-13. 298, 16610-16610 / com. Wangyz. Aspectjdemo D/TraceAspect: OnPageOpen: com. Wangyz. Aspectjdemo. SecondActivity 16:50:21. 2020-01-13, 392, 16610-16610 / com. Wangyz. Aspectjdemo D/TraceAspect: OnPageClose: com. Wangyz. Aspectjdemo. SecondActivity 16:50:22. 2020-01-13, 320, 16610-16610 / com. Wangyz. Aspectjdemo D/TraceAspect: onPageClose:com.wangyz.aspectjdemo.MainActivityCopy the code
Add start and end logs for methods
Add the annotation AddLog to the library
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AddLog {
}
Copy the code
Add the following code to TraceAspect
@Pointcut("execution(@com.wangyz.library.AddLog * *(..) )")
public void addLogPointcut(a) {}@Around("addLogPointcut()")
public void addLog(ProceedingJoinPoint joinPoint) throws Throwable {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
AddLog addLog = signature.getMethod().getAnnotation(AddLog.class);
if(addLog ! =null) {
Object target = joinPoint.getTarget();
String className = "";
if(target ! =null) {
className = target.getClass().getName();
}
Log.d(TAG, "start execute:" + className + "-" + signature.getMethod().getName());
joinPoint.proceed();
Log.d(TAG, "end execute:" + className + "-" + signature.getMethod().getName());
} else{ joinPoint.proceed(); }}Copy the code
Add the AddLog annotation to MainActivity’s onCreate
@AddLog
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/ /...
}
Copy the code
After the App is run, the following logs are generated:
2020-01-13 16:50:17.373 16610-16610/com.wangyz.aspectjdemo D/TraceAspect: start execute:com.wangyz.aspectjdemo.MainActivity-onCreate
2020-01-13 16:50:17.392 16610-16610/com.wangyz.aspectjdemo D/TraceAspect: end execute:com.wangyz.aspectjdemo.MainActivity-onCreate
Copy the code
Statistics method run time
Add the annotation ExecTime to the library
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ExecTime {
}
Copy the code
Add the following code to TraceAspect
@Pointcut("execution(@com.wangyz.library.ExecTime * *(..) )")
public void execTimePointcut(a) {}@Around("execTimePointcut()")
public void execTime(ProceedingJoinPoint joinPoint) throws Throwable {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
ExecTime execTime = signature.getMethod().getAnnotation(ExecTime.class);
if(execTime ! =null) {
long start = System.currentTimeMillis();
joinPoint.proceed();
long end = System.currentTimeMillis();
Object target = joinPoint.getTarget();
String className = "";
if(target ! =null) {
className = target.getClass().getName();
}
Log.d(TAG,
"execute time:" + className + "-" + signature.getMethod().getName() + ":" + (end - start) + "ms");
} else{ joinPoint.proceed(); }}Copy the code
Add ExecTime annotations to the onClick method
@ExecTime
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_open:
Intent intent = new Intent(this, SecondActivity.class);
startActivity(intent);
break;
default:
break; }}Copy the code
After the App is run, the following logs are generated:
The 2020-01-13 16:50:19. 272, 16610-16610 / com. Wangyz. Aspectjdemo D/TraceAspect: execute time:com.wangyz.aspectjdemo.MainActivity-onClick : 28msCopy the code
Source code address :github.com/milovetingt…