Spring Data Repository 的方面建议不起作用 [英] Aspect Advice for Spring Data Repository doesnt work

查看:28
本文介绍了Spring Data Repository 的方面建议不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为存储库创建一些切入点和之前的建议,以便为 Spring Boot 中 Spring Data 中的某些存储库启用对 entitymanager 的过滤.我在项目中也有 Web 和服务层,并且 AspectLogging 对两者都适用.但我不能对存储库做同样的事情.我已经挣扎了 2 天,我尝试了很多方法来修复它.我阅读了几乎所有关于此的文档、问题和线程(代理问题 CGlib 和 JDK 代理等).我使用 jhipster 来创建项目.

im trying to create some pointcuts and before advices for Repositories in order to enable filtering over entitymanager for some Repositories in Spring Data in Spring Boot. i also have web and service layer in project and AspectLogging works for both. But i couldnt do same for repositories. i have been struggling for 2 days and i tried so many things for fix it. i read almost every docs, issues and threads about this( proxy issues CGlib and JDK Proxy etc). i used jhipster for creating project.

我无法使用 CrudRepository 部署除@Pointcut 之外的应用程序.甚至它部署的@Before 也没有在 Repository 中调用方法调用.我想我有一个类似的问题,如以下问题.代理混淆

i cant deploy Application except @Pointcut with CrudRepository. and even its deployed @Before isnt called for a method call in Repository. i think i have a similar Problem like in following question. proxy confusion

    Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.xxx.zzz.business.repository.ApplyRepository com.xxx.zzz.web.rest.applyResource.ApplyRepository; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'applyRepository': Post-processing of FactoryBean's singleton object failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.sun.proxy.$Proxy173]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class class com.sun.proxy.$Proxy173
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:561)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
    ... 61 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'applyRepository': Post-processing of FactoryBean's singleton object failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.sun.proxy.$Proxy173]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class class com.sun.proxy.$Proxy173
    at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:116)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1523)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:314)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1120)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1044)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:942)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:533)
    ... 63 more
Caused by: org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.sun.proxy.$Proxy173]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class class com.sun.proxy.$Proxy173
    at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:212)
    at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:109)
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:447)
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:333)
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:293)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:422)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.postProcessObjectFromFactoryBean(AbstractAutowireCapableBeanFactory.java:1719)
    at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:113)
    ... 70 more
Caused by: java.lang.IllegalArgumentException: Cannot subclass final class class com.sun.proxy.$Proxy173
    at org.springframework.cglib.proxy.Enhancer.generateClass(Enhancer.java:446)
    at org.springframework.cglib.transform.TransformingClassGenerator.generateClass(TransformingClassGenerator.java:33)
    at org.springframework.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
    at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216)
    at org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:377)
    at org.springframework.cglib.proxy.Enhancer.createClass(Enhancer.java:317)
    at org.springframework.aop.framework.ObjenesisCglibAopProxy.createProxyClassAndInstance(ObjenesisCglibAopProxy.java:56)
    at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:202)
    ... 77 more

有人知道它可能是什么吗?

Does anyone know what its could be ?

类和配置如下所示.

存储库:

public interface ApplyRepository extends JpaRepository<Apply,Long>,QueryDslPredicateExecutor<Apply> {

public Page<Apply> findAll(Predicate predicate, Pageable p); 
}
...
}

数据库配置:

@Configuration
@EnableJpaRepositories("com.xxx.zzz.business.repository")
@EnableJpaAuditing(auditorAwareRef = "springSecurityAuditorAware")
@EnableTransactionManagement//(proxyTargetClass = false)
public class DatabaseConfiguration  {
....

AspectJ 配置:

AspectJ Config:

@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
// @EnableLoadTimeWeaving(aspectjWeaving = ...     )
public class LoggingAspectConfiguration {
...

系统架构:

@Aspect
public class SystemArchitecture {

/**
 * A join point is in the web layer if the method is defined
 * in a type in the com.xyz.someapp.web package or any sub-package
 * under that.W
 */
@Pointcut("within(com.xxx.zzz.web.rest..*)")
public void inWebLayer() {
}

/**
 * A join point is in the service layer if the method is defined
 * in a type in the com.xyz.someapp.service package or any sub-package
 * under that.
 */
@Pointcut("within(com.xxx.zzz.business.service..*)")
public void inServiceLayer() {
}

/**
 * A join point is in the data access layer if the method is defined
 * in a type in the com.xyz.someapp.dao package or any sub-package
 * under that.
 */
@Pointcut("within(com.xxx.zzz.business.repository..*)")
public void inDataAccessLayer() {
}



/**
 *  All layers
 */
@Pointcut("inWebLayer() || inServiceLayer() || inDataAccessLayer()")
public void inALL(){
}



 @Pointcut("within(org.springframework.data.repository.CrudRepository)")
    //@Pointcut("execution(*org.springframework.data.repository.Repository+.*               (..))")
    //@Pointcut("execution(* com.xxx.zzz.business.repository+.*(..))")
    //@Pointcut("execution(* org.springframework.data.jpa.repository.JpaRepository+.*(..))")
     //@Pointcut("execution(*        com.xxx.zzz.business.repository.ApplyRepository.*(..))")
    public void inDATAExec(){}

}

过滤器方面:

@Aspect
@Transactional
public class FilterAspect {

    private final Logger log = LoggerFactory.getLogger(this.getClass());

    @PersistenceContext
    private EntityManager entitymanager;

    @Before("com.xxx.zzz.aop.logging.SystemArchitecture.inDATAExec())") //  "execution(* com.xxx.zzz.business.repository.InvoiceRepository.*(..))"
    public void doAccessCheck() {
        if (TransactionSynchronizationManager.isActualTransactionActive() && SecurityUtils.isAuthenticated()) {
            Session session = entitymanager.unwrap(Session.class);
            session.enableFilter("GLOBAL_FILTER").setParameter("customerId", SecurityUtils.getCurrentCustomerId());
        }
    }

我解决了问题.它以某种方式与错误的切入点和名称有关.我试图更改存储库中自定义注释的切入点.它不适用于方法或类级别.我在以下链接中阅读了有关此问题的信息.建议 1 建议 2我为目标和注释奋斗了几个小时.但没有结果.在 Spring Data Repositories 中添加自定义注释以提供建议真的不可能吗?

i solved problem. it was related somehow to wrong pointscuts and names. i tried to change pointcuts for custom annotation in Repository. it doesnt work for method or class level. i read in following links issues about this. advice 1 advice 2 im struggling for hours for target and annotation. but no result. is it really imposible to add custom annotations in Spring Data Repositories for advicing ?

注释:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
//@Inherited
public @interface CustomerRequired {
    String value() default "customerrequired";
}

存储库:

public interface InvoiceRepository extends JpaRepository<Invoice,String>, QueryDslPredicateExecutor<Invoice> {

    @CustomerRequired
    public Page<Invoice> findAll(Predicate predicate, Pageable p);

     ...
}

切入点和建议:

@Pointcut(value = "@target(customerRequired)",argNames = "customerRequired")
    public void targetCustomer(@SuppressWarnings("unused") CustomerRequired customerRequired) {/**/}


@Before(value = "com.xxx.zzz.aop.logging.SystemArchitecture.targetCustomer(customerRequired) && com.xxx.zzz.aop.logging.SystemArchitecture.inDataLayer()")
public void doAccessCheck(JoinPoint joinPoint, CustomerRequired customerRequired) {
    if (TransactionSynchronizationManager.isActualTransactionActive() && SecurityUtils.isAuthenticated()) {
        Session session = entitymanager.unwrap(Session.class);
        session.enableFilter("GLOBAL_FILTER").setParameter("customerId", SecurityUtils.getCurrentCustomerId());
    }
}

推荐答案

代替使用

@Pointcut("within(org.springframework.data.repository.CrudRepository)")
public void inDATAExec(){}

如下使用

@Pointcut("this(org.springframework.data.repository.Repository)")
public void inDATAExec(){}

它的作用是

any join point (method execution only in Spring AOP) where the 
proxy implements the Repository interface

你可以看看它http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html

希望能帮到你!

这篇关于Spring Data Repository 的方面建议不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆