Java SpringAOP不适用于包含@Transactional方法的类
我开发web应用程序,需要存储重量级文件,并为此使用Apache FTP服务器。当新用户注册其帐户时,必须在远程服务器上创建名为其用户名的文件夹。为了建立连接,在执行UserCreatingServiceImpl.createUser()方法之前,我使用Spring AOP: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
@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(..))