Можно ли исключить классы интерфейса из плетения AspectJ

Сценарий:

У меня есть набор исходных файлов для классов, интерфейсов и перечислений в одном пакете, например:

package com.mycompany.data;
class Dog {
    // implementation
}

package com.mycompany.data;
class Cat {
    // implementation
}

package com.mycompany.data;
enum Gender {
    // gender options
}

package com.mycompany.data;
interface Animal {
    // methods
}

// ... plus a lot more concrete classes and a few more interfaces ...

Цель: реализовать во всех классах новый интерфейс и новый метод.

Проблема: я могу успешно вплести интерфейс в классы и исключить перечисления, но я не могу понять, как предотвратить добавление нового интерфейса к интерфейсам в пакете. .

Мой аспект в настоящее время выглядит так:

public aspect SecureAspect {
    declare parents: com.mycompany.data.* && !java.lang.Enum+ implements Secure;

    // add method from secure interface to everything implementing Secure
}

Что соответствует Dog, Cat и Animal в моем примере.

Ранее я пробовал:

declare parents: com.mycompany.data.* && java.lang.Object+ && !java.lang.Enum+ implements Secure;

потому что Animal.class.getSuperclass() == null, в отличие от Объекта, но безрезультатно.

Я знаю, что могу решить эту проблему, переместив интерфейсы из пакета (что я с радостью сделаю, если это окажется невозможным), но мне любопытно, есть ли способ исключить интерфейсы, как я сделал с перечисления.

Почти уверен, что это не имеет значения, но я использую плетение во время загрузки с javaagent.


person roblg    schedule 24.10.2013    source источник


Ответы (1)


Вопрос старый, но мне он показался интересным, и я провел небольшое исследование.

Решение выглядит так:

Аспект исключения перечислений и интерфейсов из ITD:

package com.mycompany.aspect;

import com.mycompany.data.Secure;

public aspect SecureAspect {
    declare parents :
        !is(InterfaceType) && !is(EnumType) && com.mycompany.data.*
        implements Secure;

    public void Secure.doSomething() {
        System.out.println("I am a secure " + this.getClass().getSimpleName());
    }
}

Кстати, перечисления все равно не будут реализовывать интерфейс, даже если вы их не исключите. Но тогда вы получите ошибку компилятора «невозможно использовать объявление родителей, чтобы тип перечисления com.mycompany.data.Gender реализовывал интерфейс».

Приложение драйвера, проверяющее действие ITD:

Приложение перебирает все соответствующие классы, перечисления, интерфейсы и проверяет, действительно ли они реализуют интерфейс Secure. Мы ожидаем, что перечисление Gender и интерфейс Animal будут исключены из ITD из-за пункта !is(InterfaceType) && !is(EnumType). Если интерфейс действительно реализован, метод doSomething будет вызываться через отражение, чтобы перепроверить эффект ITD.

package com.mycompany.data;

public class Application {
    public static void main(String[] args) throws Exception {
        for (Class<?> clazz : new Class[] { Application.class, Cat.class, Dog.class, Gender.class, Animal.class }) {
            String implementsYesNo = " does not implement";
            for (Class<?> iface : clazz.getInterfaces()) {
                if (iface == Secure.class) {
                    implementsYesNo = " implements";
                    Object instance = clazz.newInstance();
                    clazz.getMethod("doSomething").invoke(instance);
                    break;
                }
            }
            System.out.println(clazz.getSimpleName() + implementsYesNo + " interface Secure\n");
        }
    }
}

Вывод в консоль:

I am a secure Application
Application implements interface Secure

I am a secure Cat
Cat implements interface Secure

I am a secure Dog
Dog implements interface Secure

Gender does not implement interface Secure

Animal does not implement interface Secure

Особая благодарность Энди Клементу, сопровождающему AspectJ, который указал мне на Примечания к выпуску AspectJ 1.6.9 (ищите «Шаблоны типов категорий»), потому что в остальном эта функция не задокументирована, хотя она является официальной частью языка AspectJ.

person kriegaex    schedule 28.08.2014
comment
Спасибо! Кажется, это именно то, что я искал. - person roblg; 07.10.2014