同一个包中的@Around @Aspect 仅适用于@DependsOn
@Around @Aspect in the same package only works with @DependsOn
请参阅下面的更新。
我有一个 Spring 引导应用程序,我接受 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
没有被调用,线程被阻塞。我错过了什么?
更新:
所以这是交易:MyService
、MyServiceImpl
和 MyServiceAspect
都在同一个包中。将 MyServiceAspect
移动到另一个包使其工作。
这是否为任何人敲响了警钟?很高兴将赏金奖励给解释此行为的任何人。谢谢!
更新二:
另一个解决方案:在 MyServiceImpl
之上添加 @DependsOn(value = {"myServiceAspect"})
再次解决了问题,但仍然想知道为什么。
实际问题
正如 Alexander Paderin >> in his answer to the related 所描述的那样,afterPropertiesSet()
中的无限循环是线程阻塞程序,因为控制没有 return 返回到 Spring 在这种情况下。
1。使用您的样本的工作示例(问题编辑后不是实际的)
您提供的代码示例不直接包含问题,AspectJ声明没问题。
首先,请让我分享工作示例:spring-aspectj-sockets。它基于 Spring 5.1.0 和 AspectJ 1.9.1(当前最新版本)并使用您的示例,独立于MyServiceAspect
的 location/package。
2。问题解释
2.1。简介
样本中最可能的线程阻塞是对 ServerSocket.accept()
的调用,此方法的 javadocs 说:
Listens for a connection to be made to this socket and accepts it. The method blocks until a connection is made.
有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()
注意:如果5秒内没有连接,accept()
会抛出异常,但不会阻塞线程
2.2。假设
我假设您使用的是第一种方法,并且在某处有一条线可以初始化连接,即 clientSocket = new Socket("127.0.0.1", 18080);
。
但它被调用(例如,如果使用静态声明):
- 在
serverSocket.accept()
之后,如果 MyServiceAspect
与 位于同一个包中
- 之前 - 如果
MyServiceAspect
位于其他地方
3。调试
我不确定是否需要这个,因为赏金的描述有疑问,让我快速介绍一下以防万一。
您可以使用 远程调试 调试您的应用程序 - 它将涵盖方面、子线程、服务等 - 您只需要:
- 运行 Java 具有特定的参数,如 question >>
中所述
- 并使用IDE连接到指定的调试端口(Eclipse的步骤在同一个问题中有描述)
请参阅下面的更新。
我有一个 Spring 引导应用程序,我接受 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
没有被调用,线程被阻塞。我错过了什么?
更新:
所以这是交易:MyService
、MyServiceImpl
和 MyServiceAspect
都在同一个包中。将 MyServiceAspect
移动到另一个包使其工作。
这是否为任何人敲响了警钟?很高兴将赏金奖励给解释此行为的任何人。谢谢!
更新二:
另一个解决方案:在 MyServiceImpl
之上添加 @DependsOn(value = {"myServiceAspect"})
再次解决了问题,但仍然想知道为什么。
实际问题
正如 Alexander Paderin >> in his answer to the related afterPropertiesSet()
中的无限循环是线程阻塞程序,因为控制没有 return 返回到 Spring 在这种情况下。
1。使用您的样本的工作示例(问题编辑后不是实际的)
您提供的代码示例不直接包含问题,AspectJ声明没问题。
首先,请让我分享工作示例:spring-aspectj-sockets。它基于 Spring 5.1.0 和 AspectJ 1.9.1(当前最新版本)并使用您的示例,独立于MyServiceAspect
的 location/package。
2。问题解释
2.1。简介
样本中最可能的线程阻塞是对 ServerSocket.accept()
的调用,此方法的 javadocs 说:
Listens for a connection to be made to this socket and accepts it. The method blocks until a connection is made.
有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()
注意:如果5秒内没有连接,
accept()
会抛出异常,但不会阻塞线程
2.2。假设
我假设您使用的是第一种方法,并且在某处有一条线可以初始化连接,即 clientSocket = new Socket("127.0.0.1", 18080);
。
但它被调用(例如,如果使用静态声明):
- 在
serverSocket.accept()
之后,如果MyServiceAspect
与 位于同一个包中
- 之前 - 如果
MyServiceAspect
位于其他地方
3。调试
我不确定是否需要这个,因为赏金的描述有疑问,让我快速介绍一下以防万一。
您可以使用 远程调试 调试您的应用程序 - 它将涵盖方面、子线程、服务等 - 您只需要:
- 运行 Java 具有特定的参数,如 question >> 中所述
- 并使用IDE连接到指定的调试端口(Eclipse的步骤在同一个问题中有描述)