AspectJ ITDs: 实现通用接口

4

我希望我的类实现一个接口,但我想使用ITD在切面中提供方法的实现。这种做法可行吗?

接口:

public interface CloningService<T> {
    public T clone(T object);
}

默认实现:

public class DefaultCloningServiceImpl implements CloningService<T> {
    public T clone(T object) {
        // implementation of the clone method
    }
}

具体实现:

public class PersonService implements CloningService<Person> {
    // no code (!)
}

PersonService类会声明它实现了CloningService接口,但是方法的具体实现会在DefaultCloningServiceImpl中提供,而一个切面会将它们引入到PersonService中。

我在Eclipse.com上跟随示例尝试使用@DeclareParents来实现上述功能。然而,我从AspectJ那里得到了一个编译器错误,与泛型有关。就好像@DeclareParents注释不希望使用泛型一样...

谢谢。

2个回答

2

我建议您使用代码风格的AspectJ来解决这个问题,而不是注释风格。

您可以通过如下方式轻松实现:

aspect CloningServiceAspect {
  declare parents : PersonService extends DefaultCloningServiceImpl<Object>;
}

为了使其更普遍并与注释相关联,您可以像这样做:
aspect CloningServiceAspect {
  declare parents : (@CloningService *) extends DefaultCloningServiceImpl<Object>;
}

如果您想将此打包成独立的jar文件,只需确保要编织的所有代码将此jar文件添加到其切面路径中(如果使用编译时编织)。


Andrew,谢谢你的答案。这听起来是个好主意,但我有两个问题:(1)难道不是注解风格的AspectJ更受欢迎吗?我的印象是这是最佳实践。(2)你提供的代码扩展了PersonService,但我想扩展所有标记有注解的服务(或者其他方式),因为我想把这个逻辑放到一个单独的JAR中。是否有更适合我的解决方案? - anton1980
1
不,注解风格并不受欢迎。一方面,工具与注解风格的兼容性不佳。另一方面,有些事情仅使用注解风格无法完成(例如- intertype声明)。人们选择注解风格而非代码风格的主要原因是他们希望他们的代码可以被标准Java编译器编译(然后再运行织入器)。 - Andrew Eisenberg
我扩展了我的答案以更全面地回答你的问题。 - Andrew Eisenberg

1
我找到了解决方案!它涉及使用AspectJ的@DeclareMixin注释来混合clone()方法的默认实现:
@Aspect
public class CloningServiceAspect {
    @DeclareMixin(value = "(@CloningService *)")
    public static CloningService<?> createImplementation() {
        return new DefaultCloningServiceImpl<Object>();
    }
}

然后我的服务使用@CloningService进行注释,而不是实现接口:

@CloningService
public class PersonService {
    // no code
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接