从 AspectJ ProceedingJoinPoint 获取 Spring Bean
Get Spring Bean from AspectJ ProceedingJoinPoint
我正在寻找使用 AspectJ 获取 Spring 数据存储库接口或调用 void delete(id)
的 bean,该函数的问题是没有参数或 return 类型猜猜这个 bean,是否知道如何从 AspectJ ProceedingJoinPoint 获取调用 bean 或接口名称。
这是我的实际代码:
@Pointcut("execution(public * org.springframework.data.repository.Repository+.save(..)) || execution(public * org.springframework.data.repository.Repository+.delete(..)) && target(repository)")
public void publicNonVoidRepositoryMethod(CrudRepository repository) {
}
@Around("publicNonVoidRepositoryMethod(CrudRepository repository)")
public Object publicNonVoidRepositoryMethod(ProceedingJoinPoint pjp , CrudRepository repository) throws Throwable {
.......
}
您可以添加目标参数以获取已调用的存储库:
@Aspect
@Component
public class SampleAspect {
// Apply to all repositories in package repositories
@After("execution(* repositories.*.delete(*)) && target(repository) && args(id)")
public void afterEntityDelete(CrudRepository repository, Object id) {
...
}
}
这是一个老问题,但有人可能会觉得这有帮助。
- 为 CrudRepository、PagingAndSortingRepository 等上的所有删除方法声明切入点。:
- 当从您的代码调用时,您可以传递实体本身
- 另一方面,当通过 Spring Data REST 调用时,会使用 ID(在本例中为 Long)调用 delete 方法
在后一种情况下,我使用反射来深入了解实体类型。注意:我所有的实体都在实现 Identifiable
接口以允许轻松访问 getId()
:
@Pointcut("execution(* org.springframework.data.repository.*.delete(..)) && args(entity)")
public void repoDelete(Object entity) {}
@Around(value="repoDelete(entity)",argNames="entity")
public void onDelete(ProceedingJoinPoint pjp, Object entity) throws Throwable{
String invoker = null; //this will become the type name
Long entityId = 0L;
if (entity.getClass().getName().equals("java.lang.Long")){
entityId = (Long)entity;
REFLECT: {
// this returns a list of JPA repository-related interfaces
Class[] interfaces = jp.getTarget().getClass().getInterfaces();
for (Class iface: interfaces) {
// one of them is your JPA repository
if (iface.getName().startsWith("YOUR REPO PACKAGE")){
// the entity type can be accessed via generics
ParameterizedType pType = (ParameterizedType) iface.getGenericInterfaces()[0];
// this list contains two values - the entity type and the identifier type
Type[] typeArgs = pType.getActualTypeArguments();
for (Type t: typeArgs) {
if (t.getTypeName().startsWith("YOUR ENTITY PACKAGE")) {
invoker = t.getTypeName();
break REFLECT;
}
}
}
}
}
} else {
invoker = entity.getClass().getName();
if (entity instanceof Identifiable) entityId = (Long) ((Identifiable) entity).getId();
}
// do whatever you need ...
pjp.proceed();
}
我正在寻找使用 AspectJ 获取 Spring 数据存储库接口或调用 void delete(id)
的 bean,该函数的问题是没有参数或 return 类型猜猜这个 bean,是否知道如何从 AspectJ ProceedingJoinPoint 获取调用 bean 或接口名称。
这是我的实际代码:
@Pointcut("execution(public * org.springframework.data.repository.Repository+.save(..)) || execution(public * org.springframework.data.repository.Repository+.delete(..)) && target(repository)")
public void publicNonVoidRepositoryMethod(CrudRepository repository) {
}
@Around("publicNonVoidRepositoryMethod(CrudRepository repository)")
public Object publicNonVoidRepositoryMethod(ProceedingJoinPoint pjp , CrudRepository repository) throws Throwable {
.......
}
您可以添加目标参数以获取已调用的存储库:
@Aspect
@Component
public class SampleAspect {
// Apply to all repositories in package repositories
@After("execution(* repositories.*.delete(*)) && target(repository) && args(id)")
public void afterEntityDelete(CrudRepository repository, Object id) {
...
}
}
这是一个老问题,但有人可能会觉得这有帮助。
- 为 CrudRepository、PagingAndSortingRepository 等上的所有删除方法声明切入点。:
- 当从您的代码调用时,您可以传递实体本身
- 另一方面,当通过 Spring Data REST 调用时,会使用 ID(在本例中为 Long)调用 delete 方法
在后一种情况下,我使用反射来深入了解实体类型。注意:我所有的实体都在实现 Identifiable
接口以允许轻松访问 getId()
:
@Pointcut("execution(* org.springframework.data.repository.*.delete(..)) && args(entity)")
public void repoDelete(Object entity) {}
@Around(value="repoDelete(entity)",argNames="entity")
public void onDelete(ProceedingJoinPoint pjp, Object entity) throws Throwable{
String invoker = null; //this will become the type name
Long entityId = 0L;
if (entity.getClass().getName().equals("java.lang.Long")){
entityId = (Long)entity;
REFLECT: {
// this returns a list of JPA repository-related interfaces
Class[] interfaces = jp.getTarget().getClass().getInterfaces();
for (Class iface: interfaces) {
// one of them is your JPA repository
if (iface.getName().startsWith("YOUR REPO PACKAGE")){
// the entity type can be accessed via generics
ParameterizedType pType = (ParameterizedType) iface.getGenericInterfaces()[0];
// this list contains two values - the entity type and the identifier type
Type[] typeArgs = pType.getActualTypeArguments();
for (Type t: typeArgs) {
if (t.getTypeName().startsWith("YOUR ENTITY PACKAGE")) {
invoker = t.getTypeName();
break REFLECT;
}
}
}
}
}
} else {
invoker = entity.getClass().getName();
if (entity instanceof Identifiable) entityId = (Long) ((Identifiable) entity).getId();
}
// do whatever you need ...
pjp.proceed();
}