@Around @Aspect在同一个包中仅适用于@DependsOn

请参阅以下更新。


我有一个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并阻止该线程。 我错过了什么?

更新:

所以这是交易: MyServiceMyServiceImplMyServiceAspect都在同一个包中。 将MyServiceAspect移动到另一个包中使其工作。

这对任何人来说都响了吗? 很高兴将赏金奖励给任何解释此行为的人。 谢谢!

更新2:

另一个解决方案:在@DependsOn(value = {"myServiceAspect"})添加@DependsOn(value = {"myServiceAspect"})再次解决了这个问题,但仍然想知道为什么。

实际问题

正如Alexander Paderin >>在回答相关问题时所描述的那样>> afterPropertiesSet()中的无限循环是线程阻塞,因为在这种情况下控制不会返回到Spring

1.样本的工作示例(问题编辑后不是实际的)

您提供的代码示例不直接包含问题, AspectJ声明也没问题。

首先,请让我分享工作示例: spring-aspectj-socket 。 它基于Spring 5.1.0AspectJ 1.9.1 (目前是最新版本)并使用您的样本,独立于MyServiceAspect的位置/包工作。


2.问题解释

2.1。 介绍

样本中最可能的线程阻止程序是对ServerSocket.accept()的调用,此方法的javadocs说:

侦听对此套接字的连接并接受它。 该方法将阻塞,直到建立连接。

处理accept()有两种正确的方法:

  1. 首先初始化连接,例如:

     serverSocket = new ServerSocket(18080); clientSocket = new Socket("127.0.0.1", 18080); // initializing connection Socket socket = serverSocket.accept(); // then calling accept() 
  2. 设置超时等待接受:

     serverSocket = new ServerSocket(18080); serverSocket.setSoTimeout(5000); // 5 seconds timeout Socket socket = serverSocket.accept(); // then calling accept() 

    注意 :如果在5秒内没有连接,则accept()将抛出exception,但不会阻塞该线程

2.2。 假设

我假设您正在使用1-st方法,并且某处有一行初始化连接,即clientSocket = new Socket("127.0.0.1", 18080);

但它被调用(例如,如果使用静态声明):

  • serverSocket.accept() ,以防MyServiceAspect位于同一个包中
  • 之前 – 以防MyServiceAspect位于其他地方

3.调试

我不确定这是否需要,因为赏金的描述而有疑问,让我快速介绍一下以防万一。

您可以使用远程调试来调试应用程序 – 它将涵盖方面,子线程,服务等 – 您只需要:

  1. 使用特定参数运行Java ,如本问题中所述>>
  2. 并使用IDE连接到指定的调试端口( Eclipse的步骤在同一个问题中描述)