由于 proxy-target-class ="true"和 <aop :aspectj-autoproxy/>,Spring 无法 Autowiring

标签 spring spring-security spring-aop autowired proxy-classes

我有以下 Spring 配置:

<context:annotation-config />
<security:global-method-security jsr250-annotations="enabled"  pre-post-annotations="enabled" proxy-target-class="true" />

<tx:annotation-driven  />

<aop:aspectj-autoproxy />

<context:component-scan base-package="com.web,com.security" />

我已经在全局方法安全中启用了代理目标类,因为我想在 Controller 中使用@PreAuthorize注释(我知道Spring团队不鼓励这样做), 并在保存对象时使用aopspectJ作为服务中的“拦截器”。

似乎是因为全局方法安全中的代理配置已启用并且默认的aop方面j正在使用代理实现。它无法在所有 Controller 中 Autowiring bean。代理代理?

Controller

@RequestMapping(value = "add")
@PreAuthorize("@securityPermission.validatePermission()")
public String add(Model model) {
   //codes
}

我的带有@Aspect注释的服务类

@SuppressWarnings("serial")
@Aspect
@Service
public class InterceptorServiceImpl extends BaseServiceImplementation implements InterceptorService {
@Autowired
    private LogRepository logRepository;

@Around("execution(* com.repository.CardRequestRepository.save(..))")
@Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = Exception.class,timeout = 30)
   public Object checkProcess(ProceedingJoinPoint joinPoint) throws Throwable{
   LOGGER.info("SERVICE : START Process checking Interceptor");

}   

错误日志:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'approvalActivityController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.csl.cms.service.ApprovalActivityService com.csl.cms.web.ApprovalActivityController.approvalActivityService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'approvalActivityServiceImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.csl.cms.repository.CardRequestRepository com.csl.cms.service.serviceimplementasi.ApprovalActivityServiceImpl.cardRequestRepository; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cardRequestRepository': Post-processing of the FactoryBean's object failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.sun.proxy.$Proxy572]: 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.$Proxy572
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:287)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1106)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:607)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:925)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:472)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:388)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:293)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:111)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4791)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5285)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.manager.ManagerServlet.start(ManagerServlet.java:1256)
at org.apache.catalina.manager.ManagerServlet.doGet(ManagerServlet.java:376)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:393)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.filters.SetCharacterEncodingFilter.doFilter(SetCharacterEncodingFilter.java:108)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:581)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:936)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1004)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:722)


Caused by: org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.sun.proxy.$Proxy572]: 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.$Proxy572
at org.springframework.aop.framework.Cglib2AopProxy.getProxy(Cglib2AopProxy.java:213)
at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:112)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:477)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:362)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:322)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:407)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.postProcessObjectFromFactoryBean(AbstractAutowireCapableBeanFactory.java:1598)
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:162)
... 65 more
Caused by: java.lang.IllegalArgumentException: Cannot subclass final class class com.sun.proxy.$Proxy572
    at net.sf.cglib.proxy.Enhancer.generateClass(Enhancer.java:446)
    at net.sf.cglib.transform.TransformingClassGenerator.generateClass(TransformingClassGenerator.java:33)
    at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
    at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216)
    at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:377)
    at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:285)
    at org.springframework.aop.framework.Cglib2AopProxy.getProxy(Cglib2AopProxy.java:201)
    ... 72 more

存储库类

public interface CardRequestRepository extends JpaRepository<CardRequest, Long>, CardRequestRepositoryCustom {
public List<CardRequest> findByCardholderId(Long cardholderId);

@Query("Select cr FROM CardRequest cr "
        + "LEFT JOIN FETCH cr.cardholder ch "
        + "LEFT JOIN FETCH ch.identityDocument "
        + "LEFT JOIN FETCH cr.program p "
        + "WHERE cr.id = :id")
public CardRequest findOneFetching(@Param("id") Long cardholderId);

}

public interface CardRequestRepositoryCustom {

    public List<CardRequest> findCardRequestWithDatatablesCriterias(DatatablesCriterias criterias);
.....

服务实现类

@SuppressWarnings("serial")
@Service
public class ApprovalActivityServiceImpl extends BaseServiceImplementasi implements ApprovalActivityService {

    @Autowired
    private ApprovalActivityRepository approvalActivityRepository;
    ...
    @Autowired
    private MessageSource messageSource;

    @Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
    public ApprovalActivity findOne(Long id) {
        LOGGER.info("SERVICE : ApprovalActivity findOne id =" + id);
        return approvalActivityRepository.findOne(id);
    }
}

baseserviceimpl 类

public abstract class BaseServiceImplementasi
  implements Serializable
{
  protected transient Logger LOGGER = Logger.getLogger(getClass());
}

是否可以同时使用aop:aspectj-autoproxy并启用proxy-target-class?或者有人有其他建议吗? :)

已解决 Autowiring 失败问题

根据 @M.Deinum 的建议,我解决了 Autowiring 问题,在以下位置添加了 proxy-target-class="true"属性:

<tx:annotation-driven /> 
<cache:annotation-driven />
<aop:aspectj-autoproxy />

我用@Aspect注释删除了类中的@Service。

注意:在 InterceptorServiceImpl 中我使用 @Service 因为我希望 @Autowiring 调用存储库/服务 bean

发生的方面类问题:

似乎因为我已经删除了方面类中的@Service注释,aop方面j不知何故没有执行,并且我的日志中没有错误。

最佳答案

我解决了我的问题,似乎是因为在我的存储库类中使用了数据jpa(JpaRepository)。 这是我的 xml 配置:

<security:global-method-security jsr250-annotations="enabled" pre-post-annotations="enabled" proxy-target-class="true"/> //enabled proxy to use @preAuthorize in controller
<tx:annotation-driven />
<cache:annotation-driven />
<aop:aspectj-autoproxy />
<context:component-scan base-package="com.xxx.xxx.service.serviceimplementasi" />  
<jpa:repositories  base-package="com.csl.cms.repository" entity-manager-factory-ref="entityManagerFactory" transaction-manager-ref="transactionManager"  /> 

数据 jpa 配置:

<!--Spring Data JPA Configuration-->
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" >
        <property name="dataSource" ref="c3p0DataSource-1" />
        <property name="packagesToScan" value="com.xxx.xxx.entity"/>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="databasePlatform" value="${database.dialect}" /> 
                <property name="showSql" value="true" />
                <property name="generateDdl" value="true" />
            </bean>
        </property>
    </bean>
    <bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />        
        <property name="jpaDialect">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
        </property>
    </bean>

存储库类:

public interface CardRequestRepository extends JpaRepository<CardRequest, Long>, CardRequestRepositoryCustom {
    public List<CardRequest> findByCardholderId(Long cardholderId);

在CardRequestRepositoryCustom类中,使用entityManager创建自定义保存方法,因此它不会依赖于JpaRepository类。

public class CardRequestRepositoryImpl implements CardRequestRepositoryCustom {

    @PersistenceContext
    private EntityManager em;

 @Override
    public CardRequest customSave(CardRequest cardRequest) {
       em.persist(cardRequest);
       return cardRequest;
    }

我还在方面类中更改了切入点类,使用存储库自定义类:

@SuppressWarnings("serial")
@Aspect
@Component
public class ApprovalInterceptorServiceImpl extends BaseServiceImplementasi implements ApprovalInterceptorService {

    @Autowired
    private LifecycleLogRepository lifecycleLogRepository;
    @Autowired
    private ApprovalDefinitionRepository approvalDefinitionRepository;
    @Around("execution(* com.xxx.xxx.repository.repositoryimplementasi.CardRequestRepositoryImpl.customSave(..))")
    @Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = Exception.class,timeout = 30)
    public CardRequest checkApprovalProcess(ProceedingJoinPoint joinPoint) throws Throwable{
    LOGGER.info("SERVICE : START Approval Process checking Interceptor");
                System.out.println("SERVICE : START Approval Process checking Interceptor");

                Object messageParam[] = new Object[1];
        Object[] objs = joinPoint.getArgs();
        CardRequest cardRequest = (CardRequest) objs[0];

...

在aop方面类中,使用@Component Autowiring 服务bean,并且不使用jpaRepository扩展存储库类,而是使用/创建自定义存储库类和entityManager来保存对象。通过此配置和代码,我的代理类问题得到解决。

如果我在方面类中应用了 @Component、@Autowired 并使用 jpaRepository,则存储库 bean 类无法 Autowiring 。仍然不知道为什么会发生。

关于由于 proxy-target-class ="true"和 <aop :aspectj-autoproxy/>,Spring 无法 Autowiring ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26140939/

相关文章:

java - Spring - 拦截 bean 创建和注入(inject)自定义代理

java - java中调用另一个方法时触发一个方法(或者没有aop怎么做aop)

spring - 模拟 Keycloak token 以测试 Spring Controller

java - 我如何使用 telegram lib 在 java 中验证并向我的电话号码发送消息?

angularjs - 使用 AngularJS 通过自定义登录进行 Spring Security 身份验证

java - 启用非安全/健康端点的 Spring Boot 2

spring - Spring Boot中如何以AOP的方式实现请求超时管理

java - Spring:获取特定接口(interface)和类型的所有 Bean

spring - Jetty + Spring配置客户端证书的方法

java - 当登录用户关闭浏览器时,如何强制 Tomcat 删除过期的 session ?