2015-12-17 35 views
1

即时试图创造一些切入点,为了使在EntityManager的滤波春季数据在春季启动一些库建议对库之前。我也有项目中的web和服务层,以及AspectLogging都适用于这两者。但我不能做相同的存储库。我一直在挣扎2天,我尝试了很多东西来修复它。我几乎阅读了关于此的所有文档,问题和线索(代理问题CGlib和JDK代理等)。我用jhipster创建项目。春数据仓库方面的建议行不通

我不能只是@Pointcut与CrudRepository部署应用。甚至其部署的@Before也不需要在Repository中调用方法。我想我有一个类似的问题,如下面的问题。 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 

有谁知道它可能是什么?

类和CONFIGS看起来像下面。

库:

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的配置:

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

} 

FilterAspect:

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

编辑:我解决了问题。它在某种程度上与错误的切入点和名称有关。我试图改变Repository中定制注释的切入点。它不适用于方法或类级别。我阅读以下链接问题。 advice 1 advice 2 IM挣扎靶和注释小时。但没有结果。 在Spring Data Repositories中添加自定义注释以提供建议真的是不可能的吗?

译注:

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

回答

3

而不是使用

@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看看它

希望它能帮助!