AspectJ类型模式是否适用于具有属性的方法的所有类型? [英] AspectJ type pattern for all types with a method with an attribute?

查看:62
本文介绍了AspectJ类型模式是否适用于具有属性的方法的所有类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目前,我有标准配置:

@DeclareParents(value = "(@moody.MyAttribute *)", defaultImpl = MoodyImpl.class)

这会将我的界面+实现添加到具有 @MyAttribute

This will add my interface+implementation to any class with @MyAttribute

我想对所有具有此属性和/或具有该属性的方法的类执行此操作.

I would like to do this for all classes that have this attribute AND/OR have a method with that attribute.

所以这个类也应该获得我的界面+实现:

So this class should also get my interface+implementation:

class MyClass {
  @MyAttribute
  public void test()
  {
  }
}

有可能吗?

推荐答案

否,因为 @DeclareParents 和较新的 @DeclareMixin 都需要在其值参数.如果您是我,我将重构注解,使其仅适用于类,而不适用于方法,然后将代码也将所有注解也移至类.

No, because both @DeclareParents and the newer @DeclareMixin need class name specifications in their value parameter. If I were you I would refactor my annotation so as to only be applicable to classes, not methods, and then my code to move all annotations to classes as well.

如果您绝对想坚持自己的想法,还有一个选择:从AspectJ 1.8.2开始,有一个新的

One more option if you absolutely want to stay on your path: Since AspectJ 1.8.2 there is a new annotation processing feature. You might want to explore that one and create an annotation processor creating an ITD aspect for each affected class with annotated methods.

更新:我刚刚记得一个可以使用的非标准编译器选项 -XhasMember :

Update: I have just remembered a non-standard compiler option -XhasMember which you can use:

ajc -X

AspectJ Compiler 1.8.2 non-standard options:
    (...)
    -XhasMember         allow hasmethod() and hasfield type patterns in
                        declare parents and declare @type
    (...)

注意事项:它似乎不适用于@AspectJ语法,即您不能使用注释样式的 @DeclareParents ,而必须使用本机AspectJ语法 declare父母.默认接口的实现方式也有所不同,即在该方面通过ITD,不需要特定的实现类.

Caveat: It does not seem to work with @AspectJ syntax, i.e. you cannot use annotation-style @DeclareParents but have to use native AspectJ syntax declare parents. The default interface implementation is also done differently, i.e. via ITD in the aspect, there is no need for a specific implementation class.

这是一个可编译的,完全自洽的代码示例:

Here is a compileable, fully self-consistent code sample:

标记注释:

package de.scrum_master.app;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
public @interface MyAttribute {}

要通过ITD实现的接口:

package de.scrum_master.app;

public interface Moody {
    public void sayHelloTo(String name);
}

带有(未)标记注释的类示例:

Foo 在类级别具有注释,在方法级别的 Bar 具有注释,而 Zot 则完全没有注释.

Class Foo has the annotation at class level, Bar at method level and Zot has no annotation at all.

package de.scrum_master.app;

@MyAttribute
public class Foo {
    public static void foo() {}
}

package de.scrum_master.app;

public class Bar {
    @MyAttribute
    public static void bar() {}
}

package de.scrum_master.app;

public class Zot {
    public static void zot() {}
}

驱动程序应用程序:

出于演示目的,应用程序通过反射检查方法 sayHelloTo(String)的存在.

For demonstration purposes, the application checks for the existence of a method sayHelloTo(String) via reflection.

package de.scrum_master.app;

import java.lang.reflect.Method;

public class Application {
    public static void main(String[] args) throws Exception {
        Method method;
        try {
            method = Foo.class.getDeclaredMethod("sayHelloTo", String.class);
        } catch (NoSuchMethodException nsme) {
            method = null;
        }
        System.out.println("Foo: " + method);

        try {
            method = Bar.class.getDeclaredMethod("sayHelloTo", String.class);
        } catch (NoSuchMethodException nsme) {
            method = null;
        }
        System.out.println("Bar: " + method);

        try {
            method = Zot.class.getDeclaredMethod("sayHelloTo", String.class);
        } catch (NoSuchMethodException nsme) {
            method = null;
        }
        System.out.println("Zot: " + method);
    }
}

控制台输出(无纵横比):

Foo: null
Bar: null
Zot: null

方面:

package de.scrum_master.aspect;

import de.scrum_master.app.Moody;
import de.scrum_master.app.MyAttribute;

public aspect ITDAspect {
    declare parents : @MyAttribute * implements Moody;
    declare parents : hasmethod(@MyAttribute * *(..)) implements Moody;

    public void Moody.sayHelloTo(String name) {
        System.out.println("Hello " + name);
    }
}

控制台输出(带有方面):

Foo: public void de.scrum_master.app.Foo.sayHelloTo(java.lang.String)
Bar: public void de.scrum_master.app.Bar.sayHelloTo(java.lang.String)
Zot: null

Voilà!我们已经成功地将接口(包括其默认实现)添加到 Bar 中,该接口没有类级别的注释,而是方法级别的注释.

Voilà! We have successfully added the interface including its default implementation to Bar which does not have class-level annotation, but a method-level one.

享受!

这篇关于AspectJ类型模式是否适用于具有属性的方法的所有类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆