在 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 方面起作用了。
我在名为 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 方面起作用了。