gpt4 book ai didi

java - 使用 AspectJ 注释提供重写方法执行后的逻辑

转载 作者:行者123 更新时间:2023-12-01 10:19:10 24 4
gpt4 key购买 nike

目标:使用 AspectJ 在执行特定方法后调用静态方法。

为了解决这个问题,我们调用静态方法System.out.println和方法onConfigurationChanged

限制:

  1. onConfigurationChanged 方法是在我无法控制(无法编织)的类中声明、实现和调用的*。
  2. 由于 onConfigurationChanged 在基类中有一个实现,子类可能会也可能不会覆盖它(但 System.out.println 仍应在 >onConfigurationChanged 在两种情况下都会执行)。
  3. 使用注释语法,因为我的开发环境似乎不支持原生方面语法。

* 注意:这是在构建 Android 应用程序的上下文中,因此所讨论的基类实际上是 android.app.Activity。显然编译时编织是不可能的。我研究过加载时编织,但我有点不确定如何在这种情况下完成它,并且不确定我是否想要这样做,因为它是如此关键的代码路径。

我目前面临的主要问题实际上是子类没有重写该方法的情况。

我尝试过的:

  • 使用onConfigurationChanged签名指定执行切入点,并定义@After通知,调用System.out.println

    @After("execution(void com.jkhong..*.onConfigurationChanged()) "
    + "&& !within(DefaultOnConfigurationChangedAspect)")
    public void onConfigurationChangedExecution() {
    doDefaultOnConfigurationChanged();
    }

    private static void doDefaultOnConfigurationChanged() {
    System.out.println("Default onConfigurationChanged (mixed in)");
    }

以上方法适用于子类重写 onConfigurationChanged 方法的情况。

  • @DeclareMixin 针对子类,返回调用 System.out.println 的匿名类实现。返回的接口(interface)有一个方法,其签名与基类中的 onConfigurationChanged 完全相同。

    public interface OnConfigurationChangedListener {
    void onConfigurationChanged();
    }

    @DeclareMixin("com.jkhong..*.*Activity")
    public static OnConfigurationChangedListener createDefaultListener() {
    return new OnConfigurationChangedListener() {
    @Override
    public void onConfigurationChanged() {
    doDefaultOnConfigurationChanged();
    }
    };
    }

不幸的是,上面没有将切面提供的onConfigurationChanged实现添加到不重写onConfigurationChanged的子类中。它确实指定子类实现 OnConfigurationChangedListener 接口(interface),但由于该方法是在其父类中实现的,因此编译器不会提示。 (如果我稍微调整接口(interface)方法的签名,使其不再匹配,我会看到它确实被添加,但这不是期望的结果。)

非常感谢任何帮助,谢谢。

最佳答案

出于技术原因,您必须使用 native 语法,因为 declareparents@DeclareParents@DeclareMixin 更强大。

Eclipse 和 IntelliJ IDEA 都支持 AspectJ 原生语法。不过我不知道 NetBeans。您使用哪个 IDE? IDEA 是 Eclipse 中对高级 AspectJ 语法功能的最佳支持,但它也有一些缺点。但是,不管语法突出显示、代码完成和重构等不错的功能,您都可以在任何编辑器中编写方面。

对于您的问题,我想强调一下,我不是 Android 开发人员,因此我只是重新创建了您与这两个虚拟类一起使用的基本 Android API 功能,以便使我的方面可测试:

将它们放入一个普通的 Java 项目中(或使用原始的 Android API):

package android.app;

import android.content.res.Configuration;

public class Activity {
public void onConfigurationChanged (Configuration newConfig) {
System.out.println("onConfigurationChanged - default implementation");
}
}
package android.content.res;

public class Configuration {}

现在我们在 IDE 中创建另一个项目,这次是 AspectJ 项目。它应该引用上面的小虚拟 Android API 模拟。

在 AspectJ 项目中,我们创建两个 Activity 子类进行演示,一个重写 onConfigurationChanged ,另一个不重写它:

package com.jkhong.app;

import android.app.Activity;
import android.content.res.Configuration;

public class OverridingActivity extends Activity {
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
System.out.println("onConfigurationChanged - subclass override");
}
}
package com.jkhong.app;

import android.app.Activity;

public class NonOverridingActivity extends Activity {}

通过一个小的驱动程序应用程序,我们可以显示发生了什么:

package com.jkhong.app;

import android.app.Activity;
import android.content.res.Configuration;

public class Application {
public static void main(String[] args) {
Configuration newConfig = new Configuration();
System.out.println("Activity");
new Activity().onConfigurationChanged(newConfig);
System.out.println("\nOverridingActivity");
new OverridingActivity().onConfigurationChanged(newConfig);
System.out.println("\nNonOverridingActivity");
new NonOverridingActivity().onConfigurationChanged(newConfig);
}
}

控制台日志如下所示:

Activity
onConfigurationChanged - default implementation

OverridingActivity
onConfigurationChanged - default implementation
onConfigurationChanged - subclass override

NonOverridingActivity
onConfigurationChanged - default implementation

如您所见,OverridingActivity 在执行其他操作之前调用其 super 方法。我建议您始终这样做。对于 NonOverridingActivity 仅执行基类的默认实现,如预期的那样。

现在这是解决您的问题的方面:

package com.jkhong.aspect;

import android.app.Activity;
import android.content.res.Configuration;

public aspect ConfigurationChangeInterceptor {
public static class DefaultChangeListener extends Activity {
@Override
public void onConfigurationChanged (Configuration newConfig) {
super.onConfigurationChanged(newConfig);
doDefaultOnConfigurationChanged();
}
}

declare parents : Activity+ && !Activity extends DefaultChangeListener;

private static void doDefaultOnConfigurationChanged() {
System.out.println("onConfigurationChanged - aspect override");
}
}

请注意方面如何使用 Activity+ && !Activity 来指定“所有 Activity 子类,但不包括 Activity 本身”,以避免编译器错误,因为 Activity 无法扩展自身并且无论如何也不会暴露给编织器。

控制台日志现在如下所示:

Activity
onConfigurationChanged - default implementation

OverridingActivity
onConfigurationChanged - default implementation
onConfigurationChanged - aspect override
onConfigurationChanged - subclass override

NonOverridingActivity
onConfigurationChanged - default implementation
onConfigurationChanged - aspect override

所以现在你已经得到了你想要的。它为 NonOverridingActivityOverridingActivity 触发的日志输出。

关于java - 使用 AspectJ 注释提供重写方法执行后的逻辑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35730651/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com