无法使用spring aop

时间:2019-04-04 09:58:48

标签: spring-boot spring-data-jpa aop spring-aop hibernate-filters

我正在尝试通过尝试切入通过自定义注释EntityManager进行注释的服务实现方法,并在该方法中添加@TenantAware建议,来通过弹簧@Around启用休眠过滤器。我想启用自定义过滤器,该过滤器会在扩展where tenant_id = :tenantId的所有实体上添加一个区分符BaseEntity。因此,我创建了自定义批注,并在需要的@Transactional方法上使用它。它正在成功拦截该方法,但是当我记录它们时,变量值显示为空,并且没有设置过滤器。

该项目是spring-boot 2应用程序,我正在使用spring aop创建方面。我正在使用Hibernate 5作为JPA实施提供程序。

无法加载SimpleJpaRepository.class的加载时间,因为它不会公开noarg构造函数。

这是我的TenantFilterAdvisor班。

package org.foo.bar.advisors;

@Aspect
@Slf4j
@Component
public class TenantFilterAdvisor {

    @PersistenceContext
    private EntityManager entityManager;

    public TenantFilterAdvisor() {
        log.debug("###########################################################################");
        log.debug("###################### Tenant Advisor Filter Started ######################");
        log.debug("###########################################################################");
    }

    @Pointcut(value = "@annotation(org.foo.bar.TenantAware)")
    public void methodAnnotatedWithTenantAware() {
    }

    @Pointcut(value = "execution(public * * (..))")
    public void allPublicMethods() {

    }

    @Around(value = "methodAnnotatedWithTenantAware() && allPublicMethods()")
    public Object enableTenantFilter(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {

        log.debug("###########################################################################");
        log.debug("###################### Before enabling tenant filter ######################");
        log.debug("###########################################################################");

        if (null != entityManager) {

            log.debug("Tenant filter name: ", "tenantFilter");
            log.debug("Tenant filter property: ", "tenantId");
            log.debug("Setting tenant id to: ", new Long(10));

            Session session = entityManager.unwrap(Session.class);
            Filter filter = session.enableFilter("tenantFilter");
            filter.setParameter("tenantId", new Long(10));

        }


        Object result = proceedingJoinPoint.proceed();

        // Code to disable the hibernate filter goes here.
        log.debug("###########################################################################");
        log.debug("###################### After disabling tenant filter ######################");
        log.debug("###########################################################################");

        return result;

    }

}

服务接口和实现类的相关部分是

public interface InventoryService {
    Inventory getInventoryById(Long id);
}
@Service
public class InventoryServiceImpl implements InventoryService {

    @Autowired
    private InventoryRepository repo;

    @Override
    @Transactional
    @TenantAware
    public Inventory getInventoryById(Long id) {
       LOG.debug("getInventoryById() called  with: id = {}", id);
        final Optional<Inventory> inventoryOp = repo.findById(id);

        if (inventoryOp.isPresent()) {
            return inventoryOp.get();
        } else {
            throw new InventoryNotFoundException(String.format(MESSAGE_INVENTORY_NOT_FOUND_FOR_ID, id));
        }
    }
}

存储库界面为

@Repository
@Transactional(readOnly = true)
public interface InventoryRepository extends BaseRepository<Inventory, Long> {  
}

BaseRepository接口扩展了JpaRepository。

方面配置类是

@Configuration
@ComponentScan(basePackages = {"org.foo.bar.advisors"})
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class AOPConfig {
}

最后,其他类继承的相关MappedSuperClass具有定义为的过滤器

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@MappedSuperclass
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@FilterDef(
        name = "tenantFilter",
        parameters = @ParamDef(name = "tenantId", type = "long")
)
@Filter(name = "tenantFilter", condition = "tenant_id = :tenantId")
public abstract class BaseTransactionalEntity extends BaseEntity {

    @Column(name = "tenant_id", nullable = false)
    private Long tenantId;

}

如果需要详细信息,这里是皮肤注释类

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Inherited
public @interface TenantAware {
}

我需要在会话中启用休眠过滤器,并在继续连接点完成执行后禁用它。但事实并非如此。我想念什么?

1 个答案:

答案 0 :(得分:1)

Hibernate Reference Guide过滤器中所述,过滤器仅适用于实体查询,不适用于直接提取。在您的代码中,您正在通过findById进行直接提取,这直接转换为entityManager.find,因此是直接提取。

您可以重写Spring JPA存储库,并重新实现findById作为实体查询而不是直接获取,以解决此问题。