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

标签 java aop aspectj aspectj-maven-plugin

我也有这样的情况。 这是我的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,但没有成功。 我只是设法让类实现 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是您在方面定义的任何接口(interface)实现的子类,例如这样的事情:

@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;
}

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

  • 这些方法尝试从 future 的 VillageDao 子类 Village 访问静态方法,因此您无法在 VillageDao 中声明静态方法,而必须直接在 Village 中声明它们。
  • 如果您直接在 VillageDao 中声明它们,您可以调用它们,例如通过 VillageDao.insertVillage(this),但是签名 public static void insertVillage(Village Village) 将不再适合,因为 this 是一个 VillageDao,而不是它自己的子类 Village
  • 由于类似的原因,您无法调用 this.getVid(),因为 thisVillageDao 而不是 Village >,但 getter 方法在原始 Village 类中具有固定签名。

等等。 Java 编译器的功能还不够强大,无法完成 AspectJ 编译器所做的事情:将代码直接编织到原始类文件中。

因此:请坚持使用 native 语法。它不仅更强大,而且在我看来也更具可读性。我一直不明白为什么这么多人试图将强大的 AspectJ 引入糟糕的替代 @AspectJ 语法。不知何故,他们似乎相信他们可以从纯 Java 语法中获益。我不同意。它们只是技术手段的退化,而且糟糕的语法根本不适合用于成熟的 AOP。

关于java - 使用方面注释将类型间声明从 .aj 转换为 .java,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36780990/

相关文章:

java - 如何使用泛型使语句正确

java 运算符优先级 DOT 与逻辑 AND

java - 反射:get Object state from return type of method in runtime

java - 使用 spring aop 分析 jar 文件中的方法没有发生

java - 修改编辑距离算法以不计算所有距离

java - 如何在JAVA中播放flv、mp4、avi格式视频?

c# - 如何使用 PostSharp 属性注入(inject)属性?

aop - 什么是面向方面的编程?

aop - 面向方面编程在现实世界中的用途是什么?

gradle + aspectj ----编译错误编织外部jar