Wenn Sie beispielsweise am Anfang und am Ende einer Methode protokollieren möchten, ist es realistisch, sie für jede Methode zu schreiben? Möchten Sie diesen Prozess in eine bestimmte Methode einbetten, um die Verarbeitungszeit für die Leistungsmessung zu messen und Ihren Code dafür zu ändern? Beide sind Nein, nicht wahr? Aspektorientierte Programmierung bietet eine "relativ einfache" Möglichkeit, sie zu lösen. Indem Sie dies einbeziehen, können Sie sich auf jedes Interesse konzentrieren.
Ich habe nach verschiedenen Artikeln gesucht, aber ich konnte keinen Artikel finden, der auf Japanisch geschrieben wurde, also [hier](https://fernandocejas.com/2014/08/03/aspect-oriented-programming- Schreibe einen Artikel basierend auf in-android /). Grundsätzlich folgt der Code der Referenzseite.
Ich werde die Frage weglassen, was aspektorientierte Programmierung ist. Weitere wissenschaftliche Inhalte und Begriffe finden Sie in anderen Artikeln und in der Literatur.
Von hier aus erkläre ich das Verfahren, um etwas zu machen, das konkret funktioniert.
Zuvor werden Sie in diesem Artikel aufgefordert, den Quellcode in Ihr Projekt aufzunehmen. Wenn Sie es als anderes Projekt ausschneiden und als Bibliothek zum Projekt hinzufügen möchten, lesen Sie es bitte entsprechend. Ich denke, das einzige, was Sie lesen müssen, ist build.gradle neu zu schreiben.
Ich werde die folgenden zwei Methoden dafür erklären.
Ersteres verwendet auch AspectJ, aber das Plug-In übernimmt die mühsamen Einstellungen für Sie. Daher ist es einfach einzurichten. Letzterer verwendet AspectJ so wie es ist, daher müssen Sie den Prozess zum Erstellen in app / build.gradle schreiben, um ihn zu erstellen.
Markieren Sie zunächst, um den Vorgang zu unterbrechen. Das Wahrzeichen ist eine Anmerkung.
DebugTraceBefore.java
@Retention(RetentionPolicy.CLASS)
@Target({ ElementType.METHOD })
public @interface DebugTraceBefore {}
DebugTraceAround.java
@Retention(RetentionPolicy.CLASS)
@Target({ ElementType.METHOD })
public @interface DebugTraceAround {}
Weitere Informationen zur Aufbewahrung und zum Ziel von Anmerkungen finden Sie in einem anderen Artikel.
Wir haben zwei Arten von Sehenswürdigkeiten vorbereitet.
debugtracebefore
Vor der Methode, mit der diese Anmerkung festgelegt wurde,
debugtracearound
Ermöglicht die Unterbrechung der Verarbeitung vor und nach der Methode, in der diese Anmerkung festgelegt ist.
Der Name der Anmerkung ist beliebig.
Schreiben Sie als Nächstes, welche Art der Verarbeitung unterbrochen ist. Dieses Mal werde ich den Prozess schreiben, um das Protokoll auszugeben.
@aspect
Ist ein Zeichen dafür, dass hier der Prozess der Unterbrechung durch aspektorientierte Programmierung geschrieben ist.
@pointcut
Setzen Sie nun eine Markierung, um den Vorgang zu unterbrechen.
Rufen wir die Methode mit dieser Annotation als Punktschnittmethode </ b> auf.
@before
Oder@after
、@around
Gibt an, wo der Prozess unterbrochen werden soll, und gibt an, welche Pointcut-Methode unterbrochen werden soll.
Der Methodenname ist willkürlich, aber es ist eine gute Idee, ihm einen beschreibenden Namen zu geben.
DebugTraceBefore usw. sind Anmerkungen, also Ausführung(...)unter@Es ist angehängt.
Wenn es sich um eine Methode der angegebenen Klasse handelt, kann sie als `` `Ausführung (void android.app.Activity.onCreate (..))` `angegeben werden.
#### **`execution(...)Sie müssen den vollständigen Paketnamen für angeben.`**
AspectDebugLog.java
@Aspect
public final class AspectDebugLog {
private static final String POINTCUT_BEFORE_METHOD =
"execution(@com.test.aspectorientationprogrammingsample.aspect.DebugTraceBefore * *(..))";
private static final String POINTCUT_AROUND_METHOD =
"execution(@com.test.aspectorientationprogrammingsample.aspect.DebugTraceAround * *(..))";
@Pointcut(POINTCUT_BEFORE_METHOD)
public void pointcutDebugTraceBefore() {}
@Pointcut(POINTCUT_AROUND_METHOD)
public void pointcutDebugTraceAround() {}
@Pointcut("execution(void android.app.Activity.onCreate(..))")
public void pointcutOnCreate() {}
@Before("pointcutOnCreate()")
public void weavePreOnCreate(JoinPoint joinPoint) {
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
String className = methodSignature.getDeclaringType().getSimpleName();
Log.d("Aspect", "### weavePreOnCreate: " + className);
}
@After("pointcutOnCreate()")
public void weavePostOnCreate(JoinPoint joinPoint) throws Throwable {
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
String className = methodSignature.getDeclaringType().getSimpleName();
Log.d("Aspect", "### weavePostOnCreate: " + className);
}
@Before("pointcutDebugTraceBefore()")
public void weaveDebugTraceBefore(JoinPoint joinPoint) throws Throwable {
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
String className = methodSignature.getDeclaringType().getSimpleName();
String methodName = methodSignature.getName();
Log.d("Aspect", "### weaveDebugTraceBefore: " + className + " " + methodName);
}
@Around("pointcutDebugTraceAround()")
public Object weaveDebugTraceAround(ProceedingJoinPoint joinPoint) throws Throwable {
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
String className = methodSignature.getDeclaringType().getSimpleName();
String methodName = methodSignature.getName();
Log.d("Aspect", "### weaveDebugTraceAround - start: " + className + " " + methodName);
Object result = joinPoint.proceed();
Log.d("Aspect", "### weaveDebugTraceAround - end: " + className + " " + methodName);
return result;
}
}
Erstellen Sie als Nächstes einen Bildschirm.
MainActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.button1).setOnClickListener(
new View.OnClickListener() {
@Override
@DebugTraceAround
public void onClick(View view) {
Log.d("Log", "### onClick: button1");
}
});
findViewById(R.id.button2).setOnClickListener(
new View.OnClickListener() {
@Override
@DebugTraceBefore
public void onClick(View view) {
Log.d("Log", "### onClick: button2");
}
});
}
// @Override
// public void onResume() {
// super.onResume();
// }
@Override
@DebugTraceBefore
public void onPause() {
super.onPause();
}
}
Es ist ein Bildschirm mit nur zwei Tasten.
onCreate(...)Die diesmal erstellte Anmerkung ist nicht festgelegt.
```onpause() ```Um das Protokoll vorher auszugeben```debugtracebefore```Angegeben.
Ich habe eine Anmerkung festgelegt, um ein Protokoll auszugeben, auch wenn auf die Schaltfläche geklickt wird.
Das war's zum Schreiben von Java-Code.
Von hier aus schreiben Sie build.gradle neu.
## So verwenden Sie das Plug-In
In der Methode zur Verwendung des Plug-Ins werde ich ein Beispiel für die Verwendung dieses Plug-Ins vorstellen.
[GradleAspectJ-Android](https://github.com/Archinamon/android-gradle-aspectj)
#### **`app/build.gradle`**
```gradle
//Von hier aus hinzufügen
buildscript {
repositories {
jcenter()
mavenCentral()
maven { url "https://jitpack.io" }
}
dependencies {
classpath 'com.github.Archinamon:GradleAspectJ-Android:3.0.3'
}
}
//Addiere hier
apply plugin: 'com.android.application'
apply plugin: 'com.archinamon.aspectj'//hinzufügen
android {
compileSdkVersion 27
buildToolsVersion "27.0.1"
defaultConfig {
applicationId "com.test.aspectorientationprogrammingsample"
minSdkVersion 21
targetSdkVersion 27
versionCode 1
versionName "1.0.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
multiDexEnabled true
minifyEnabled true // true:Verschleiert(Es ist erforderlich, Klassen, Methoden usw. festzulegen, die nicht entsprechend verschleiert werden.)、false:Nicht verschleiern
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:27.+'
compile 'com.android.support.constraint:constraint-layout:1.0.2'
testCompile 'junit:junit:4.12'
}
Es gibt einige Kommentare auf dem Weg, aber es ist in Ordnung, sie zu löschen.
app/build.gradle
//Von hier aus hinzufügen
import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main
buildscript {
repositories {
jcenter()
mavenCentral()
}
dependencies {
classpath 'org.aspectj:aspectjtools:1.8.1'
}
}
//Addiere hier
apply plugin: 'com.android.application'
android {
compileSdkVersion 27
buildToolsVersion "27.0.1"
defaultConfig {
applicationId "com.test.aspectorientationprogrammingsample"
minSdkVersion 21
targetSdkVersion 27
versionCode 1
versionName "1.0.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
multiDexEnabled true
minifyEnabled true // true:Verschleiert(Es ist erforderlich, Klassen, Methoden usw. festzulegen, die nicht entsprechend verschleiert werden.)、false:Nicht verschleiern
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
//Von hier aus hinzufügen
applicationVariants.all { variant ->
// JavaCompile javaCompile = variant.javaCompile// use javaCompiler instead of javaCompile
// javaCompile.doLast {
// //
// }
variant.javaCompiler.doLast {
String[] args = ["-showWeaveInfo",
"-1.8",
"-inpath", javaCompile.destinationDir.toString(),
"-aspectpath", javaCompile.classpath.asPath,
"-d", javaCompile.destinationDir.toString(),
"-classpath", javaCompile.classpath.asPath,
"-bootclasspath", project.android.bootClasspath.join(
File.pathSeparator)]
MessageHandler handler = new MessageHandler(true);
new Main().run(args, handler)
def log = project.logger
for (IMessage message : handler.getMessages(null, true)) {
switch (message.getKind()) {
case IMessage.ABORT:
case IMessage.ERROR:
case IMessage.FAIL:
log.error message.message, message.thrown
break;
case IMessage.WARNING:
case IMessage.INFO:
log.info message.message, message.thrown
break;
case IMessage.DEBUG:
log.debug message.message, message.thrown
break;
}
}
}
}
//Addiere hier
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:27.+'
compile 'com.android.support.constraint:constraint-layout:1.0.2'
testCompile 'junit:junit:4.12'
compile 'org.aspectj:aspectjrt:1.8.1'//hinzufügen
}
Wenn Sie dies tun, wird das Protokoll wie folgt ausgegeben: (Da das Lesen schwierig wird, werden Zeit usw. gelöscht.)
D/Aspect: ### weavePreOnCreate: MainActivity
D/Aspect: ### weavePostOnCreate: MainActivity
D/Aspect: ### weaveDebugTraceBefore: MainActivity onPause
D/Aspect: ### weaveDebugTraceAround - start: onClick
D/Log: ### onClick: button1
D/Aspect: ### weaveDebugTraceAround - end: onClick
D/Aspect: ### weaveDebugTraceBefore: onClick
D/Log: ### onClick: button2
Ich habe auch bestätigt, dass es in meiner Umgebung funktioniert, aber wie war es in Ihrer Umgebung? Hat es funktioniert?
Ein zu beachtender Punkt ist, dass `Ausführung (void android.app.Activity.onCreate (..))` `in`
Ausführung (void android.app.Activity.onResume ()) `` geändert werden kann Es wird kein Protokoll ausgegeben.
Weil MyActivity onResume nicht überschreibt.
Protokolle nicht implementierter Methoden werden nicht ausgegeben.
Es ist natürlich.
Jetzt können Sie die zusätzliche Logik ausschneiden!
Appendix
Wir haben den Betrieb in der folgenden Umgebung bestätigt.
Umgebung | Ausführung |
---|---|
Mac OS | Sierra 10.12.6 |
Android Studio | 2.3.3 |
Java version | 8 |
Gradle version | 3.3 |
Android Plugin version | 2.3.3 |
Recommended Posts