首先,请记住,在 Java 中,一个类只能有一个超类(使用“extends”关键字),但您可以有多个接口(实现)。因此,您可能希望改为使用“实现”而不是“扩展”。
下面展示了如何按照 Ramnivas Laddad 的 AspectJ in Action, 2nd Edition(第 5 章)中的说明进行混合样式方法。当您能够让类实现接口并且您希望提供默认实现时,这种风格很有效。
package com.example.aop.attributes;
import java.util.Calendar;
import javax.persistence.Column;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.NotNull;
/**
* Aspect that adds a timestamp attribute to the entity along with the logic to
* update that timestamp value just before it gets persisted to the database. It
* also adds a creation timestamp to track when the object was originally
* created.
*
* @author tgh
*
*/
public interface Timestamped {
public Calendar getCreationTimestamp();
public void setCreationTimestamp(Calendar creationTimestamp);
public Calendar getModificationTimestamp();
public void setModificationTimestamp(Calendar modificationTimestamp);
/**
* AspectJ MixIn for any class which implements the interface. Provides a
* default implementation using AspectJ. This is the style shown in
* Manning's AspectJ in Action (2nd edition) for providing a default
* implementation interface.
*
* @author tgh
*/
static aspect Impl {
@NotNull
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "created", nullable=false)
private Calendar Timestamped.creationTimestamp = Calendar.getInstance();
@NotNull
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "last_modified", nullable=false)
private Calendar Timestamped.modificationTimestamp = Calendar.getInstance();
public Calendar Timestamped.getCreationTimestamp() {
return this.creationTimestamp;
}
public void Timestamped.setCreationTimestamp(Calendar creationTimestamp) {
this.creationTimestamp = creationTimestamp;
}
public Calendar Timestamped.getModificationTimestamp() {
return this.modificationTimestamp;
}
public void Timestamped.setModificationTimestamp(Calendar modificationTimestamp) {
this.modificationTimestamp = modificationTimestamp;
}
@PrePersist
@PreUpdate
private void Timestamped.updateModificationTimestampDuringPrePersistAndPreUpdate() {
this.modificationTimestamp = Calendar.getInstance();
}
}
}
要使用上述内容,您只需将“implements Timestamped”添加到实体类。这是在类中引入成员(新属性)的最简单方法。您还可以使用源上的注释进行混音。
在无法修改源的情况下,您将不得不与声明的父母一起玩。如果只标记在其类声明中已经有“@Entity”的实体,这将是:
declare parents: @Entity * implements Slf4jLoggerAspect;
或者:
declare parents: (@MakeLoggable *) implements Slf4jLogger;
如果您的接口位于单独的包中,那么您可以尝试仅标记特定包(而不是接口包)的 TypePattern:
declare parents: my.class.package.* implements Slf4jLogger;
并且根据 AspectJ in Action (2nd Ed) 中的第 3.5 章,您还可以在 Type Pattern 元素上使用二元运算符:
declare parents: (@Entity *) || (@MakeLoggable *) implements Slf4jLogger;
我不能 100% 确定上述方法是否有效,但有一个“||” 二元运算符,我已经看到在其他地方使用过(但找不到链接)。
(不,我不认为你可以告诉类型模式只看类而不看接口。虽然可能有 hasMethod() 和 hasField() 但它们在书中被标记为实验性的。)