请参阅下面的更新。
我有一个 Spring Boot 应用程序,我接受 TCP/IP 连接:
public MyClass implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
try (ServerSocket serverSocket = new ServerSocket(port)) {
while (true) {
Socket socket = serverSocket.accept();
new ServerThread(socket).start();
}
}
}
...
private class ServerThread extends Thread {
@Override
public void run() {
try (InputStream input = socket.getInputStream();
OutputStream output = socket.getOutputStream()) {
// Read line from input and call a method from service:
service.myMethod(lineConvertedToMyObject);
} catch {
...
}
}
}
}
现在效果很好,就这样。但是当我将 AspectJ 介绍给myMethod
:
@Aspect
@Component
public class MyServiceAspect {
private static final Logger logger = LoggerFactory.getLogger(MyServiceAspect.class);
@Around(value = "execution(* com.package.to.MyService.myMethod(..))")
public MyObject rules(ProceedingJoinPoint joinPoint) throws Throwable {
long startTime = System.currentTimeMillis();
MyObject obj = (MyObject) joinPoint.proceed();
logger.debug("Took {} milliseconds", System.currentTimeMillis() - startTime);
return obj;
}
}
service.myMethod
没有被调用并且线程被阻塞。我缺少什么?
Update:
所以这是交易:MyService
, MyServiceImpl
and MyServiceAspect
都在同一个包中。移动MyServiceAspect
到另一个包中使其工作。
这对任何人来说都敲响了警钟吗?很高兴向任何解释此行为的人提供赏金。谢谢!
更新2:
另一种解决方案:添加@DependsOn(value = {"myServiceAspect"})
在之上MyServiceImpl
再次解决了问题,但仍然想知道为什么。
实际问题
正如所描述的亚历山大·帕德林 >> https://stackoverflow.com/users/3985168/alexander-paderin在他对相关问题的回答中问题>> https://stackoverflow.com/questions/52518312/cacheable-doesnt-intercept-the-method-cache-is-always-empty/52609074#52609074中的无限循环afterPropertiesSet()
是线程阻塞程序,因为控制权没有返回到Spring在这种情况下。
1.使用您的示例的工作示例(问题编辑后不是实际的)
您提供的代码示例不直接包含问题,AspectJ声明没问题。
首先,请让我分享一下工作示例:spring-aspectj-套接字 https://github.com/marme1ad/spring-aspectj-sockets。它是基于春季5.1.0 and 方面J 1.9.1(当前最新版本)并使用您的示例,其工作独立于位置/包MyServiceAspect
.
2.问题说明
2.1.介绍
示例中最可能的线程阻止程序是调用ServerSocket.accept()
,此方法的 javadocs 说:
侦听与此套接字建立的连接并接受它。该方法将阻塞,直到建立连接为止。
有2种正确的处理方法accept()
:
-
首先初始化连接,例如:
serverSocket = new ServerSocket(18080);
clientSocket = new Socket("127.0.0.1", 18080); // initializing connection
Socket socket = serverSocket.accept(); // then calling accept()
-
设置等待接受的超时时间:
serverSocket = new ServerSocket(18080);
serverSocket.setSoTimeout(5000); // 5 seconds timeout
Socket socket = serverSocket.accept(); // then calling accept()
NOTE:如果5秒内没有连接,accept()
会抛出异常,但不会阻塞线程
2.2.假设
我假设您正在使用第一种方法,并且在某处有一行初始化连接,即clientSocket = new Socket("127.0.0.1", 18080);
.
但它被调用(例如,如果使用静态声明):
- After
serverSocket.accept()
以防万一MyServiceAspect
位于同一个包中并且
- 之前 - 以防万一
MyServiceAspect
位于其他地方
3、调试
我不确定是否需要这样做,由于赏金的描述而有疑问,让我快速介绍一下,以防万一。
您可以使用调试您的应用程序远程调试- 它将涵盖方面、子线程、服务等。 - 您只需要:
- Run Java具有特定的参数,如本节中所描述的问题>> https://stackoverflow.com/questions/975271/remote-debugging-a-java-application
- 并使用IDE连接到指定的调试端口(步骤为Eclipse在同一问题中描述)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)