在 JpaRepository 上调用 delete 方法时未调用 AspectJ 方法

AspectJ method not being called when calling delete method on JpaRepository

我在名为 seedrecord 的对象和名为 affiliatelink 的对象之间建立了多对多关系。为了删除 affiliatelink,我需要先从每个 seedrecord 的 affiliateList 中删除对它的引用。之后,我使用 spring Jparepository 的删除方法删除对象。因为我的服务 (AffiliateLinkService) 中有不同的删除方法,所以我决定将这段代码放在 AspectJ class 中。但是,当调用 deletemethod 时,不会在此之前调用 aspectJ 方法。谁能看看我的代码并告诉我哪里出了问题?

@Before("execution(* org.springframework.data.jpa.repository.JpaRepository.delete(..))" +
        "&& within(Services.AffiliateLinkService) && args(entity)")
private void deleteAffiliateLinkFromSeedRecordAffiliateLists(Object entity){
    log.info("hailing from SystemListenerService!");
    ((AffiliateLink)entity).getSeedRecords()
            .forEach(seedRecord -> {
                seedRecord.getAffiliateLinks()
                        .remove(seedRecord);
                seedRecordDao.save(seedRecord);
            });
}

编辑:问题不是由 jparepository 方法引起的。因为当我使用名为 deleteMe() 的包装器方法更改删除方法并让方面方法 运行 在此包装器方法之前它也不起作用..

@Before("execution(* Services.AffiliateLinkService.deleteMe(..))" +
        "&& args(entity)")

另外,为了您的信息,我将方面声明为 bean,配置 class 声明为 @EnableAspectJAutoProxy

编辑 2:当我在 @Afterthrowing("execution(* *(..))") 中更改 @Before 时,事情变得更奇怪了。

然后我在应用程序启动期间突然收到此错误。

Description:

The bean 'dataSourceInitializer' could not be injected as a 'org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer' because it is a JDK dynamic proxy that implements: org.springframework.context.ApplicationListener

Action:

Consider injecting the bean as one of its interfaces or forcing the use of CGLib-based proxies by setting proxyTargetClass=true on @EnableAsync and/or @EnableCaching.

问题是我没有明确声明一个名为 dataSourceInitializer 的 bean,所以我不能用 @Enable this or that 来注释它...天哪,我多么讨厌 Spring.

PS:我有另一个方法在返回 jparepository 的保存方法后调用,它很有用,所以我不明白为什么删除建议不起作用。这里是工作方法的注释。

@AfterReturning("execution(* org.springframework.data.jpa.repository.JpaRepository.save(..))" + "&& !within(Services.SystemListenerService) && args(entity)")

编辑 3:它与我正在使用的 AffiliateLink 参数有关。例如,当我用 long 替换 AffiliateLink 参数时,将调用 before 方法……这是 Affiliatelink pojo。但是我不认为 pojo 有什么不寻常的地方会导致这个:

@Entity
public class AffiliateLink implements Serializable {
    @Id
    @GeneratedValue(generator = "ID_GENERATOR")
    private Long id;

    @URL
    private String affiliateUrl;

    @URL
    private String affiliateImageUrl;

    private String title;

    private String description;

    private Double productValue;

    private boolean general;

    private byte rank;

    private boolean linkBroken;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(updatable = false)
    @CreationTimestamp
    private Date creationDate;


    @ElementCollection @CollectionTable( name = "affiliate_keywords", joinColumns=@JoinColumn(name = "id", referencedColumnName = "id") ) @Column(name="keyword")
    private Set<String> keywords;

    @ManyToMany(mappedBy = "affiliateLinks")
    private Set<SeedRecord> seedRecords = new HashSet<>();

    @Enumerated(EnumType.STRING)
    private LocalizedStorefront localizedStorefront;

    private long seedId;

    private boolean plantClimbs;

    private boolean spicy;

    private boolean teaPlant;

    public AffiliateLink() { }

    public AffiliateLink(AffiliateLinkCreateDTO affiliateLinkCreateDTO) {
        this.title = affiliateLinkCreateDTO.getTitle();
        this.description = affiliateLinkCreateDTO.getDescription();
        this.general = affiliateLinkCreateDTO.isGeneral();
        this.rank = affiliateLinkCreateDTO.getRank();
        this.localizedStorefront = affiliateLinkCreateDTO.getLocalizedStorefront();
        this.productValue = affiliateLinkCreateDTO.getProductValue();
        this.keywords = affiliateLinkCreateDTO.getKeywords();
        this.seedId = affiliateLinkCreateDTO.getSeedId() != null ? affiliateLinkCreateDTO.getSeedId() : 0;
    }

    public AffiliateLink(String affiliateUrl,
                         String affiliateImageUrl,
                         String title,
                         String description,
                         Double productValue,
                         boolean general,
                         byte rank,
                         boolean linkBroken,
                         Set<String> keywords,
                         LocalizedStorefront localizedStorefront,
                         long seedId,
                         boolean plantClimbs,
                         boolean spicy,
                         boolean teaPlant) {
        this.affiliateUrl = affiliateUrl;
        this.affiliateImageUrl = affiliateImageUrl;
        this.title = title;
        this.description = description;
        this.productValue = productValue;
        this.general = general;
        this.rank = rank;
        this.linkBroken = linkBroken;
        this.keywords = keywords;
        this.localizedStorefront = localizedStorefront;
        this.seedId = seedId;
        this.plantClimbs = plantClimbs;
        this.spicy = spicy;
        this.teaPlant = teaPlant;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Date getCreationDate() {
        return creationDate;
    }

    public void setCreationDate(Date creationDate) {
        this.creationDate = creationDate;
    }

    public boolean isPlantClimbs() {
        return plantClimbs;
    }

    public void setPlantClimbs(boolean plantClimbs) {
        this.plantClimbs = plantClimbs;
    }

    public boolean isSpicy() {
        return spicy;
    }

    public void setSpicy(boolean spicy) {
        this.spicy = spicy;
    }

    public boolean isTeaPlant() {
        return teaPlant;
    }

    public void setTeaPlant(boolean teaPlant) {
        this.teaPlant = teaPlant;
    }

    public long getSeedId() {
        return seedId;
    }

    public void setSeedId(long seedId) {
        this.seedId = seedId;
    }

    public Double getProductValue() {
        return productValue;
    }

    public void setProductValue(Double productValue) {
        this.productValue = productValue;
    }

    public String getAffiliateImageUrl() {
        return affiliateImageUrl;
    }

    public boolean isLinkBroken() {
        return linkBroken;
    }

    public void setLinkBroken(boolean linkBroken) {
        this.linkBroken = linkBroken;
    }

    public void setAffiliateImageUrl(String affiliateImageUrl) {
        this.affiliateImageUrl = affiliateImageUrl;
    }

    public String getAffiliateUrl() {
        return affiliateUrl;
    }

    public void setAffiliateUrl(String affiliateUrl) {
        this.affiliateUrl = affiliateUrl;
    }

    public String getTitle() {
        return title;
    }

    public Set<String> getKeywords() {
        return keywords;
    }

    public void setKeywords(Set<String> keywords) {
        this.keywords = keywords;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public boolean isGeneral() {
        return general;
    }

    public void setGeneral(boolean general) {
        this.general = general;
    }

    public byte getRank() {
        return rank;
    }

    public void setRank(byte rank) {
        this.rank = rank;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public Set<SeedRecord> getSeedRecords() {
        return seedRecords;
    }

    public void setSeedRecords(Set<SeedRecord> seedRecords) {
        this.seedRecords = seedRecords;
    }

    public LocalizedStorefront getLocalizedStorefront() {
        return localizedStorefront;
    }

    public void setLocalizedStorefront(LocalizedStorefront localizedStorefront) {
        this.localizedStorefront = localizedStorefront;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        AffiliateLink that = (AffiliateLink) o;
        return general == that.general &&
                rank == that.rank &&
                Objects.equals(id, that.id) &&
                Objects.equals(affiliateUrl, that.affiliateUrl) &&
                Objects.equals(affiliateImageUrl, that.affiliateImageUrl) &&
                Objects.equals(title, that.title) &&
                Objects.equals(description, that.description) &&
                Objects.equals(productValue, that.productValue) &&
                localizedStorefront == that.localizedStorefront;
    }

    @Override
    public int hashCode() {

        return Objects.hash(id, affiliateUrl, affiliateImageUrl, title, description, productValue, general, rank, localizedStorefront);
    }
}

好吧,我在 spring 论坛上用 post 解决了这个问题。 http://forum.spring.io/forum/spring-projects/aop/100146-aspect-advice-is-never-called

方法应该 public 不是静态的并且在外部调用(这意味着该方法应该在另一个 class 中)。所以我将 deleteMe 方法移动到另一个 class 并从那里调用它,现在 @Before 方面起作用了。