Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/352.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java SpringAOP不适用于包含@Transactional方法的类_Java_Spring_Spring Aop_Spring Aspects - Fatal编程技术网

Java SpringAOP不适用于包含@Transactional方法的类

Java SpringAOP不适用于包含@Transactional方法的类,java,spring,spring-aop,spring-aspects,Java,Spring,Spring Aop,Spring Aspects,我开发web应用程序,需要存储重量级文件,并为此使用Apache FTP服务器。当新用户注册其帐户时,必须在远程服务器上创建名为其用户名的文件夹。为了建立连接,在执行UserCreatingServiceImpl.createUser()方法之前,我使用Spring AOP: @Component @Aspect public class RemoteServerConnectionEstablisher { private static boolean connectionEstabl

我开发web应用程序,需要存储重量级文件,并为此使用Apache FTP服务器。当新用户注册其帐户时,必须在远程服务器上创建名为其用户名的文件夹。为了建立连接,在执行UserCreatingServiceImpl.createUser()方法之前,我使用Spring AOP:

@Component
@Aspect
public class RemoteServerConnectionEstablisher {
    private static boolean connectionEstablished = false;

    @Autowired
    private RemoteServerConnector serverConnector;

    @Pointcut("execution(* com.storehouse.business.services.impl.UserCreatingServiceImpl.createUser(..)) ||"
            + " execution (* com.storehouse.business.services.impl.ItemCreatingServiceImpl.createItem(..)) ||"
            + "execution (* com.storehouse.business.services.impl.FileDownloadingServiceImpl.downloadFile(..))")
    public void pointcut() {
    }

    @Before("pointcut()")
    public void establishConnection(JoinPoint jp) {
        if (!connectionEstablished) {
            if (serverConnector.connectToRemoteServer()) {
                connectionEstablished = true;
            }
        }

    }

    @After("pointcut()")
    public void disconnect(JoinPoint jp) {
        if (connectionEstablished) {
            if (serverConnector.disconnect()) {
                connectionEstablished = false;
            }
        }
    }
}
以下是带有createUser()方法的服务类:

一切都很顺利,直到我将@Transactional方法添加到服务类:

@Transactional
public void checkIfUsernameExist(String username) {

}

现在方面类的方法不调用。你能解释一下原因吗。提前感谢您的帮助。

问题在于您的切入点表达式

execution(* com.storehouse.business.services.impl.UserCreatingServiceImpl.createUser(..))
您正在拦截
usercreatingserviceinpl
上的
createUser
方法的执行。当您不添加为您的实现创建代理的内容时,这种方法就起作用了。因为您将直接调用此方法

但是,当您添加了
@Transactional
时,将创建一个代理,并且现在将在
UserCreatingService
上完成方法调用,因为该接口将保留创建的代理。默认情况下,spring使用基于接口的JDK动态代理

要解决这些问题,请执行以下操作之一

  • 重写切入点以在接口上操作,而不是实现类
  • 使用基于类的代理,而不是基于接口的代理
  • 使用编译或加载时编织
  • 重写切入点 使用
    execution(*com.storeory.business.services.UserCreatingService+.createUser(..)
    而不是您现在拥有的。这将使用接口而不是具体类

    使用基于类的代理 假设您使用了
    @EnableAspectJAutoProxy
    proxyTargetClass=true
    添加到它,导致
    @EnableAspectJAutoProxy(proxyTargetClass=true)
    。这将创建基于类的代理,并应使原始切入点工作

    使用编译或加载时编织 除了使用代理,您还可以更改生成/加载代码的方式。对于编译时编织,您必须修改构建以使用AspectJ编译器在编译时应用方面,这样您就不再需要代理了

    或者,您可以添加
    @enableAspectJoutoproxy
    ,而不是
    @enableAloadTimeWeaving
    ,如果您使用最新的servlet容器,它将在加载类时立即编织方面


    这两种方法都可以消除对代理的需求(至少在这一部分中是这样),并且可以使原始切入点工作。

    是否定义了自动扫描?如果您的意思是您的切入点不正确,您不应该针对类,但接口将
    usercreatingserviceinpl
    替换为
    UserCreatingService+
    (如果
    impl
    包中没有这个,那么也把它删除。是的,你说得对。我已经改变了切入点,现在一切都正常了。
    execution(* com.storehouse.business.services.impl.UserCreatingServiceImpl.createUser(..))