java - 是否有适用于所有类(而非接口(interface))的 AspectJ TypePattern?

标签 java logging aspectj spring-roo

我正在尝试使用 AspectJ 自动将记录器字段添加到我的所有类中,以避免我必须在每个类中单独编写样板记录器信息。在我看来,这是一种相当常见的做法,但我还没有找到任何现有的方面来实现这一点。

这个方面本身相当简单:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public privileged aspect Slf4jLoggerAspect{

    public interface Slf4jLogger{}
    private final Logger Slf4jLogger.logger = LoggerFactory.getLogger(getClass());

    declare parents: ????? extends Slf4jLogger;
}

我的大问题是我该放什么?我希望 TypePattern 指示所有类,但不指示接口(interface)。如果我尝试仅使用 * 模式,它也会拾取我的所有接口(interface)。

AspectJ 中有什么东西可以让我只挑选出我的所有类定义吗?

或者这样的东西已经存在了吗?我本想/期望在 Roo 中看到这一点,但找不到 slf4j roo 插件或注释。

谢谢!

埃里克

最佳答案

首先,请记住,在 Java 中,一个类只能有一个父类(super class)(使用“extends”关键字),但可以有多个接口(interface)(实现)。因此,您可能想要更改为使用“实现”而不是“扩展”。

下面展示了如何执行混合风格方法,如 Ramnivas Laddad 的《AspectJ in Action》第二版(第 5 章)中所述。当您能够让类实现接口(interface)并且您想要提供默认实现时,这种风格非常有效。

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;

如果您的接口(interface)位于单独的包中,那么您可以尝试仅标记特定包(而不是接口(interface)包)的 TypePattern:

declare parents: my.class.package.* implements Slf4jLogger;

根据 AspectJ in Action(第 2 版)中的第 3.5 章,您还可以在类型模式元素上使用二元运算符:

declare parents: (@Entity *) || (@MakeLoggable *) implements Slf4jLogger;

我不是100%确定上面的方法有效,但是有一个“||”二元运算符,我在其他地方看到过它的使用(但找不到链接)。

(不,我认为你不能告诉类型模式只查看类而不查看接口(interface)。虽然可能有 hasMethod() 和 hasField() 但它们在书中被标记为实验性的。)

关于java - 是否有适用于所有类(而非接口(interface))的 AspectJ TypePattern?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13422230/

相关文章:

java - 当我尝试使用改造上传图像时,我得到空值

java - 在 Tomcat 6 中为 Java 的 GC 消息添加时间戳

javascript - 记录我网站上的超链接点击

aspectj - 如何使用aspectj围绕aspect修改未知数量的方法参数

java - Aspectj 切入点捕获流关闭(尝试测量通过套接字发送/接收的字节)

java - AspectJ LTW 无法与 JMX 远程配合使用

java - MCRYPT_RIJNDAEL_256 Java 中的 PHP 加密

java - 使用 StringBuilder 连接查询字符串

python - 如何在没有检测的情况下记录所有内容

java - 从外部配置文件读取值返回空值