WebSocketHandlerScanner.java
package sprout.server.websocket.endpoint;
import sprout.beans.annotation.Component;
import sprout.context.BeanFactory;
import sprout.mvc.mapping.PathPattern;
import sprout.mvc.mapping.PathPatternResolver;
import sprout.server.websocket.annotation.*;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
@Component
public class WebSocketHandlerScanner {
private final WebSocketEndpointRegistry endpointRegistry;
private final PathPatternResolver pathPatternResolver;
public WebSocketHandlerScanner(WebSocketEndpointRegistry endpointRegistry, PathPatternResolver pathPatternResolver) {
this.endpointRegistry = endpointRegistry;
this.pathPatternResolver = pathPatternResolver;
}
public void scanWebSocketHandlers(BeanFactory context) {
Collection<Object> beans = context.getAllBeans();
System.out.println(beans.size() + " beans found for WebSocket scan.");
for (Object bean : beans) {
Class<?> beanClass = bean.getClass();
if (beanClass.isAnnotationPresent(WebSocketHandler.class)) {
System.out.println("Found @WebSocketHandler: " + beanClass.getName());
WebSocketHandler webSocketHandlerAnn = beanClass.getAnnotation(WebSocketHandler.class);
String classLevelPath = webSocketHandlerAnn.value(); // @WebSocketHandler의 value()는 엔드포인트 경로
PathPattern pathPattern = pathPatternResolver.resolve(classLevelPath);
Method onOpenMethod = null;
Method onCloseMethod = null;
Method onErrorMethod = null;
Map<String, Method> messageMappings = new HashMap<>();
for (Method method : beanClass.getMethods()) { // public 메서드 스캔
method.setAccessible(true); // 리플렉션 호출을 위해
if (method.isAnnotationPresent(OnOpen.class)) {
onOpenMethod = method;
} else if (method.isAnnotationPresent(OnClose.class)) {
onCloseMethod = method;
} else if (method.isAnnotationPresent(OnError.class)) {
onErrorMethod = method;
} else if (method.isAnnotationPresent(MessageMapping.class)) {
MessageMapping messageMappingAnn = method.getAnnotation(MessageMapping.class);
String messagePath = messageMappingAnn.value();
messageMappings.put(messagePath, method);
}
// TODO: 메서드 시그니처 (파라미터 타입) 검증 로직 추가 (WebSocketSession, String message 등)
}
endpointRegistry.registerEndpoint(pathPattern, bean, onOpenMethod, onCloseMethod, onErrorMethod, messageMappings);
}
}
}
}