使用方面注释将类型间声明从 .aj 转换为 .java

Convert Inter-Type declaraton from .aj to .java with Aspect annotations

我有这种情况。 这是我的 Village.java:

public class Village{

    private Integer vid;
    private String villageName;
    private String district;

    public Integer getVid() {
        return vid;
    }
    public void setVid(Integer vid) {
        this.vid = vid;
    }
    public String getVillageName() {
        return villageName;
    }
    public void setVillageName(String villageName) {
        this.villageName = villageName;
    }
    public String getDistrict() {
        return district;
    }
    public void setDistrict(String district) {
        this.district = district;
    }
}

这是我的Dao.java界面:

public interface Dao<T> {
    public void insert();
    public void update();
    public void delete();
}

这是我的方面Village_Dao.aj(你可以忽略静态方法逻辑):

import org.apache.ibatis.session.SqlSession;
import com.madx.finance.data.utils.persistence.Dao;
import com.madx.finance.data.utils.factory.ConnectionFactory;

public aspect Village_Dao {
    declare parents: Village implements Dao<Village>;

    public void Village.insert() {
        Village.insertVillage(this);
    }

    public void Village.update() {
        Village.updateVillage(this);
    }

    public void Village.delete() {
        Village.deleteVillage(this.getVid());
    }

    public Village Village.getData() {
        return Village.getDataVillage(this.getVid());
    }

    public static void Village.insertVillage(Village village) {
        SqlSession session = ConnectionFactory.getSqlSessionFactory().openSession();
        VillageMapper mapper = session.getMapper(VillageMapper.class);
        mapper.insertVillage(village);
        session.commit();
        session.close();
    }

    public static void Village.updateVillage(Village village) {
        SqlSession session = ConnectionFactory.getSqlSessionFactory().openSession();
        VillageMapper mapper = session.getMapper(VillageMapper.class);
        mapper.updateVillage(village);
        session.commit();
        session.close();
    }

    public static void Village.deleteVillage(Integer id) {
        SqlSession session = ConnectionFactory.getSqlSessionFactory().openSession();
        VillageMapper mapper = session.getMapper(VillageMapper.class);
        mapper.deleteVillage(id);
        session.commit();
        session.close();
    }

    public static Village Village.getDataVillage(Integer id) {
        SqlSession session = ConnectionFactory.getSqlSessionFactory().openSession();
        VillageMapper mapper = session.getMapper(VillageMapper.class);
        Village village = mapper.selectVillage(id);
        session.close();
        return village;
    }
}

我正在尝试将 Village_Dao.aj 转换为带注释的版本 Village_Dao_Java.java,但没有成功。 我刚刚设法使 class 实现 Dao,但我无法编写方法(在此文件 Village_Dao_Java.java 中分别插入、更新和删除)。

这是 Village_Dao_Java.java 的版本(仍未完成)(我读过这个 link 但我无法在这种情况下使用它):

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.DeclareParents;

import com.madx.finance.data.utils.persistence.Dao;

@Aspect
public class Village_Dao_Java {

    @DeclareParents("com.madx.demo.Village")
    private Dao<Village> implementedInterface;
}

@AspectJ 风格无法满足您的需求,您需要使用更强大的原生语法。 (你为什么要切换?)

这背后的原因是 Java 编译器只能将 @DeclareParents 转换为 Village 是您定义的任何接口实现的子 class 的形式在您方面,例如这样的事情:

@Aspect
public class Village_Dao_Java {
    public static class VillageDao implements Dao<Village> {
        @Override
        public void insert() {
            Village.insertVillage(this);
        }

        @Override
        public void update() {
            Village.updateVillage(this);
        }

        @Override
        public void delete() {
            Village.deleteVillage(this.getVid());
        }

        public Village getData() {
            return getDataVillage(this.getVid());
        }

    }

    @DeclareParents(
        value = "de.scrum_master.app.Village",
        defaultImpl = VillageDao.class
    )
    private Dao<Village> villageDao;
}

但是这种方法有几个问题:

  • 这些方法试图访问来自未来VillageDao子classVillage的静态方法,所以你不能在VillageDao中声明静态方法但必须声明它们直接在 Village 中。
  • 如果您直接在 VillageDao 中声明它们,您可以调用它们,例如通过 VillageDao.insertVillage(this),但签名 public static void insertVillage(Village village) 将不再适用,因为 thisVillageDao,而不是它自己的子 class Village.
  • 出于类似的原因,您不能调用 this.getVid(),因为 thisVillageDao 而不是 Village,但是 getter 方法具有固定的签名原来Villageclass.

等等。 Java 编译器不够强大,无法完成 AspectJ 编译器所做的工作:将代码直接编织到原始 class 文件中。

因此:请坚持使用原生语法。它不仅更强大,而且 IMO 也更具可读性。我一直不明白为什么那么多人试图将强大的 AspectJ 哄骗到糟糕的替代 @AspectJ 语法中。不知何故,他们似乎相信他们可以从纯 Java 语法中获益。我不同意。他们只是得到了技术手段的退化和糟糕的语法,从来没有打算用于成熟的 AOP。