服务层的Spring AOP

时间:2013-08-21 23:27:18

标签: java spring-mvc proxy aop spring-aop

我需要一些Spring AOP的帮助。 我有以下代码:


@Service
public class UserSecurityService implements UserDetailsService {

    @Autowired
    private UserService userService;
    ....
}

@Service
public class UserService extends CrudService<User, UserRepository> {

    public UserService() {
        super();
    }

    @Autowired
    public UserService(UserRepository repository) {
        super(repository);
        this.repository = repository;
    }
    ....
}

@Repository
interface UserRepository extends JpaRepository<User, String> {
     ...
}

应用context.xml中

<import resource="classpath*:spring/application-context-db.xml" />
<import resource="classpath*:spring/application-context-aop.xml" />
<import resource="classpath*:spring/application-context-mail.xml" />
<import resource="application-context-security.xml" />

<context:component-scan base-package="com.xpto">
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository" />
</context:component-scan>

应用上下文-aop.xml文件

<aop:aspectj-autoproxy />
<aop:config>
    <aop:aspect id="serviceLoggingAspect" ref="serviceLoggingAspectBean">
        <aop:pointcut id="servicePointcut"
                expression="@within(org.springframework.stereotype.Service)" />

        <aop:before method="before" pointcut-ref="servicePointcut" />
        <aop:after-returning method="afterReturning" pointcut-ref="servicePointcut" returning="result" />
        <aop:after-throwing method="afterThrowing" pointcut-ref="servicePointcut" throwing="exception" />
    </aop:aspect>
</aop:config>

当我尝试在Tomcat上加载我的应用程序时,出现以下异常:

Caused by: java.lang.IllegalArgumentException: Can not set com.xpto.user.service.UserService field com.xpto.user.security.service.UserSecurityService.userService to com.sun.proxy.$Proxy57
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:164)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:168)
at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:81)
at java.lang.reflect.Field.set(Field.java:680)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:510)
... 35 more

我在Web层使用相同的配置来记录我的应用程序并且工作正常,但是当我将AOP放在服务层时,我得到了这个例外。

我正在使用Spring MVC,在web.xml中,我配置为加载两个不同的上下文,一个只加载@ Controller,另一个加载@Repository和@Service。

2 个答案:

答案 0 :(得分:16)

您没有注入接口,因此您需要使用CGLIB代理,spring reference manual状态:

  

Spring AOP默认使用AOP代理的标准J2SE动态代理。这样可以代理任何接口(或接口集)。

     

Spring AOP也可以使用CGLIB代理。这是代理类而不是接口所必需的。如果业务对象未实现接口,则默认使用CGLIB。由于优化的做法是编程接口而不是类,业务类通常会实现一个或多个业务接口。

Spring决定使用J2SE代理(com.sun.proxy.$Proxy57),因为CrudService实现了一个接口。要强制使用CGLIB,您可以调整XML:

<aop:aspectj-autoproxy proxy-target-class="true"/>

答案 1 :(得分:4)

  

Spring决定使用J2SE代理(com.sun.proxy。$ Proxy57),因为CrudService实现了一个接口。

@samlewis:你写的这句话促使我创建了我的服务接口,当我这样做时,LoggingAspect工作得非常好。所以,我没有使用 proxy-target-class = true

非常感谢你的时间。