Introductions

引入(在 AspectJ 中称为类型间声明)使方面能够声明被建议的对象实现给定接口,并代表这些对象提供该接口的实现。

Introductions (known as inter-type declarations in AspectJ) enable an aspect to declare that advised objects implement a given interface, and to provide an implementation of that interface on behalf of those objects.

你可以使用 @DeclareParents 注释进行引入。该注释用于声明匹配类型有一个新父类(因此得名)。例如,给定一个名为 UsageTracked 的接口和一个名为 DefaultUsageTracked 的该接口的实现,以下方面声明服务接口的所有实现者还实现 UsageTracked 接口(例如,通过 JMX 统计):

You can make an introduction by using the @DeclareParents annotation. This annotation is used to declare that matching types have a new parent (hence the name). For example, given an interface named UsageTracked and an implementation of that interface named DefaultUsageTracked, the following aspect declares that all implementors of service interfaces also implement the UsageTracked interface (e.g. for statistics via JMX):

  • Java

  • Kotlin

@Aspect
public class UsageTracking {

	@DeclareParents(value="com.xyz.service.*+", defaultImpl=DefaultUsageTracked.class)
	public static UsageTracked mixin;

	@Before("execution(* com.xyz..service.*.*(..)) && this(usageTracked)")
	public void recordUsage(UsageTracked usageTracked) {
		usageTracked.incrementUseCount();
	}

}
@Aspect
class UsageTracking {

	companion object {
		@DeclareParents(value = "com.xyz.service.*+",
			defaultImpl = DefaultUsageTracked::class)
		lateinit var mixin: UsageTracked
	}

	@Before("execution(* com.xyz..service.*.*(..)) && this(usageTracked)")
	fun recordUsage(usageTracked: UsageTracked) {
		usageTracked.incrementUseCount()
	}
}

要实现的接口由注释字段的类型确定。@DeclareParents 注释的 value 特性是 AspectJ 类型模式。匹配类型的任何 bean 都实现 UsageTracked 接口。请注意,在前一个示例的 before 建议中,服务 bean 可以直接用作 UsageTracked 接口的实现。如果你以编程方式访问 bean,则可以编写以下内容:

The interface to be implemented is determined by the type of the annotated field. The value attribute of the @DeclareParents annotation is an AspectJ type pattern. Any bean of a matching type implements the UsageTracked interface. Note that, in the before advice of the preceding example, service beans can be directly used as implementations of the UsageTracked interface. If accessing a bean programmatically, you would write the following:

  • Java

  • Kotlin

UsageTracked usageTracked = context.getBean("myService", UsageTracked.class);
val usageTracked = context.getBean<UsageTracked>("myService")