【问题标题】:Get Spring Bean from AspectJ ProceedingJoinPoint从 AspectJ ProceedingJoinPoint 获取 Spring Bean
【发布时间】:2015-06-01 05:41:10
【问题描述】:

我正在寻找使用 AspectJ 获取 Spring Data Repository 接口或调用 void delete(id) 的 bean,该函数的问题是没有参数或返回类型来猜测 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 {

.......
}

【问题讨论】:

    标签: spring spring-boot spring-data aspectj


    【解决方案1】:

    您可以添加目标参数以获取已调用的存储库:

    @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) {
        ...
        }
    }
    

    【讨论】:

    • 感谢您的回答,但我尝试根据自己的情况对其进行调整,但没有成功,您能否检查一下我上面的代码。
    • 老实说,我在使用@Before@After 获得目标方面有很好的经验——这种解决方案根本不需要@Poincut。到目前为止,我还没有弄清楚如何使用@Around 进行设置。
    【解决方案2】:

    这是一个老问题,但有人可能会觉得这很有帮助。

    • 为 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();
    }
    

    【讨论】:

      猜你喜欢
      • 2011-08-08
      • 1970-01-01
      • 2017-07-18
      • 1970-01-01
      • 2014-02-12
      • 2016-04-03
      • 1970-01-01
      • 2014-02-21
      • 1970-01-01
      相关资源
      最近更新 更多