Par exemple, si vous souhaitez vous connecter au début et à la fin d'une méthode, est-il réaliste de l'écrire pour chaque méthode? En supposant que vous intégriez ce processus dans une méthode particulière pour mesurer le temps de traitement pour la mesure des performances, souhaitez-vous modifier votre code pour cela? Les deux sont non, non? La programmation orientée aspect fournit un moyen "relativement simple" de les résoudre. En incorporant cela, vous pouvez vous concentrer sur chaque intérêt.
J'ai cherché divers articles, mais je n'ai pas trouvé un article écrit en japonais, donc [ici](https://fernandocejas.com/2014/08/03/aspect-oriented-programming- Rédigez un article basé sur in-android /). Fondamentalement, le code suit la page de référence.
Je vais omettre la question de savoir ce qu'est la programmation orientée aspect. Veuillez vous référer à d'autres articles et littérature pour le contenu et les termes académiques.
De là, j'expliquerai la procédure pour faire quelque chose qui fonctionne concrètement.
Avant cela, cet article vous amènera à inclure le code source dans votre projet. Si vous souhaitez le découper comme un autre projet et l'ajouter au projet en tant que bibliothèque, veuillez le lire comme il convient. Je pense que la seule chose que vous devez lire est de réécrire build.gradle.
Je vais expliquer les deux méthodes suivantes pour cela.
Le premier utilise également AspectJ, mais le plug-in fait les réglages fastidieux pour vous. Par conséquent, il est facile à configurer. Ce dernier utilise AspectJ tel quel, vous devez donc écrire le processus à construire dans app / build.gradle pour construire.
Tout d'abord, faites une marque pour interrompre le processus. Le repère est une annotation.
DebugTraceBefore.java
@Retention(RetentionPolicy.CLASS)
@Target({ ElementType.METHOD })
public @interface DebugTraceBefore {}
DebugTraceAround.java
@Retention(RetentionPolicy.CLASS)
@Target({ ElementType.METHOD })
public @interface DebugTraceAround {}
Veuillez vous référer à un autre article pour la conservation et la cible des annotations.
Nous avons préparé deux types de points de repère.
debugtracebefore
Avant la méthode qui a défini cette annotation,
debugtracearound
Permet d'interrompre le traitement avant et après la méthode dans laquelle cette annotation est définie.
Le nom de l'annotation est arbitraire.
Ensuite, écrivez le type de traitement interrompu. Cette fois, j'écrirai le processus pour sortir le journal.
@aspect
C'est une marque que le processus d'interruption par la programmation orientée aspect est écrit ici.
@pointcut
Maintenant, définissez une marque pour interrompre le processus.
Appelons la méthode avec cet ensemble d'annotations comme méthode de coupure par point </ b>.
@before
Ou@after
、@around
Indique où interrompre le processus et spécifie la méthode de coupe ponctuelle à interrompre.
Le nom de la méthode est arbitraire, mais c'est une bonne idée de lui donner un nom descriptif.
DebugTraceBefore etc. sont des annotations, donc l'exécution(...)parmi@Est attaché.
S'il s'agit d'une méthode de la classe spécifiée, elle peut être spécifiée comme ```execution (void android.app.Activity.onCreate (..)) `` `.
#### **`execution(...)Vous devez spécifier le nom complet du package pour.`**
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;
}
}
Ensuite, créez un écran.
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();
}
}
C'est un écran avec seulement deux boutons.
onCreate(...)L'annotation créée cette fois n'est pas définie.
```onpause() ```Pour sortir le journal avant```debugtracebefore```Est spécifié.
J'ai défini une annotation pour générer un journal même lorsque vous cliquez sur le bouton.
C'est tout pour écrire du code Java.
À partir de là, réécrivez build.gradle.
## Comment utiliser le plug-in
Dans la méthode d'utilisation du plug-in, je présenterai un exemple d'utilisation de ceci.
[GradleAspectJ-Android](https://github.com/Archinamon/android-gradle-aspectj)
#### **`app/build.gradle`**
```gradle
//Ajouter à partir d'ici
buildscript {
repositories {
jcenter()
mavenCentral()
maven { url "https://jitpack.io" }
}
dependencies {
classpath 'com.github.Archinamon:GradleAspectJ-Android:3.0.3'
}
}
//Ajouter ici
apply plugin: 'com.android.application'
apply plugin: 'com.archinamon.aspectj'//ajouter à
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:Brouiller(Il est nécessaire de définir des classes, des méthodes, etc. qui ne s'obscurcissent pas comme il convient.)、false:N'obscurcissez pas
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'
}
Il y a quelques commentaires en cours de route, mais vous pouvez les supprimer.
app/build.gradle
//Ajouter à partir d'ici
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'
}
}
//Ajouter ici
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:Brouiller(Il est nécessaire de définir des classes, des méthodes, etc. qui ne s'obscurcissent pas comme il convient.)、false:N'obscurcissez pas
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
//Ajouter à partir d'ici
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;
}
}
}
}
//Ajouter ici
}
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'//ajouter à
}
Lorsque vous faites cela, le journal sera généré comme suit: (Comme il devient difficile à lire, l'heure, etc. est supprimée.)
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
J'ai également confirmé que cela fonctionne dans mon environnement, mais comment était-ce dans votre environnement? Cela a-t-il fonctionné?
Un point à noter est que execution (void android.app.Activity.onCreate (..)) `` `` peut être changé en
execution (void android.app.Activity.onResume ())
Aucun journal n'est sorti.
Parce que MyActivity ne remplace pas onResume.
Les journaux des méthodes non implémentées ne sont pas générés.
C'est naturel.
Maintenant, vous pouvez supprimer la logique supplémentaire!
Appendix
Nous avons confirmé l'opération dans l'environnement suivant.
environnement | version |
---|---|
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