작성
·
103
0
안녕하세요, 몇가지 질문이 있습니다.
선생님의 코드대로 쳤는데 제 인텔리제이에서는 왜 다음과 같은 에러가 발생하는지 모르겠습니다.
왜 LogDemoController가 static 컨텍스트라고 떠서 이런 에러가 발생하는지 모르겠습니다.
제가 봤을땐 static이 아닌데 말이죠 (MyLogger, Controller, Service 모두 static은 없음)
여기까지의 소스 코드를 1차 첨부합니다. (에러 발생 코드)
package hello.core.common;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import java.util.UUID;
@Component
@Scope(value="request")
public class MyLogger {
private String uuid; // unique id
private String requestURL;
public void setRequestURL(String requestURL){
this.requestURL = requestURL;
}
public void log(String message){
System.out.println("[" + uuid + "] " + "[" + requestURL + "]" + message);
}
@PostConstruct
public void init(){
uuid = UUID.randomUUID().toString();
System.out.println("[" + uuid + "] " + "[" + requestURL + "] request scope bean create : " + this);
}
@PreDestroy
public void close(){
System.out.println("[" + uuid + "] " + "[" + requestURL + "] request scope bean close : " + this);
}
/*
로그를 출력하기 위한 클래스
request 스코프로 지정했으며, HTTP 요청당 하나씩 생성되고, HTTP 요청이 끝나는 시점에 소멸된다.
이 빈이 생성되는 시점에 자동으로 @PostConstruct 초기화 메서드를 사용해서 uuid를 생성해서 저장해둔다.
이 빈은 HTTP 요청 당 하나씩 생성되므로, uuid를 저장해두면 다른 HTTP 요청과 구분할 수 있다.
requestURL은 빈이 생성되는 시점에는 알 수 없으므로 외부에서 setter로 입력받는다.
*/
}
package hello.core.web;
import hello.core.common.MyLogger;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequiredArgsConstructor
public class LogDemoController {
private final LogDemoService logDemoService;
private final ObjectProvider<MyLogger> myLoggerProvider; // 스프링 컨테이너가 뜨면서 의존관계 주입을 해야하는데 mylogger는 request scope이라 아직 고객 요청이 없어서 에러
@RequestMapping("log-demo")
@ResponseBody
public String logDemo(HttpServletRequest request){
String requestURL = request.getRequestURL().toString(); // 고객이 요청한 url을 받을 수 있음
MyLogger myLogger = myLoggerProvider.getObject(); // 주입 시점에 주입 받을 수 있음
myLogger.setRequestURL(requestURL);
myLogger.log("controller test");
LogDemoService.logic("testId");
return "OK";
}
}
package hello.core.web;
import hello.core.common.MyLogger;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class LogDemoService {
private final ObjectProvider<MyLogger> myLoggerProvider;
public void logic(String id) {
MyLogger myLogger = myLoggerProvider.getObject();
myLogger.log("service id = " + id);
}
}
어쨋든 이 문제를 해결하지 않으면 소스 코드 실행이 되지 않습니다. 따라서 intelliJ 가이드에 따라 static으로 만들어주고 실행을 하면 또 에러가 발생합니다.
private final ObjectProvider<MyLogger> myLoggerProvider;
위 구문 초기화를 하라는 가이드에 = Null을 해주면
소스 코드 실행 시 (디버깅 결과) myLoggerProvider.getObject() 에서 널포인트 익셉션이 터집니다.
여기까지 상황의 코드를 2차 첨부합니다.
package hello.core.web;
import hello.core.common.MyLogger;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequiredArgsConstructor
public class LogDemoController {
private final LogDemoService logDemoService;
private final ObjectProvider<MyLogger> myLoggerProvider; // 스프링 컨테이너가 뜨면서 의존관계 주입을 해야하는데 mylogger는 request scope이라 아직 고객 요청이 없어서 에러
@RequestMapping("log-demo")
@ResponseBody
public String logDemo(HttpServletRequest request){
String requestURL = request.getRequestURL().toString(); // 고객이 요청한 url을 받을 수 있음
MyLogger myLogger = myLoggerProvider.getObject(); // 주입 시점에 주입 받을 수 있음
myLogger.setRequestURL(requestURL);
myLogger.log("controller test");
LogDemoService.logic("testId");
return "OK";
}
}
package hello.core.web;
import hello.core.common.MyLogger;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class LogDemoService {
private static final ObjectProvider<MyLogger> myLoggerProvider = null;
public static void logic(String id) {
MyLogger myLogger = myLoggerProvider.getObject();
myLogger.log("service id = " + id);
}
}
어떻게 해결해야할까요? 제가 잘못 타이핑한 부분이 있다면 말씀 부탁드립니다.
답변 1
1
안녕하세요. 멍토님, 공식 서포터즈 y2gcoder입니다.
일단 먼저 1번 상태에서 사진을 보시면 LogDemoController의 멤버 변수인 LogDemoService logDemoService 가 사용되지 않아 회색인 것을 보실 수 있습니다!
package hello.core.web;
import hello.core.common.MyLogger;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequiredArgsConstructor
public class LogDemoController {
private final LogDemoService logDemoService;
private final ObjectProvider<MyLogger> myLoggerProvider; // 스프링 컨테이너가 뜨면서 의존관계 주입을 해야하는데 mylogger는 request scope이라 아직 고객 요청이 없어서 에러
@RequestMapping("log-demo")
@ResponseBody
public String logDemo(HttpServletRequest request){
String requestURL = request.getRequestURL().toString(); // 고객이 요청한 url을 받을 수 있음
MyLogger myLogger = myLoggerProvider.getObject(); // 주입 시점에 주입 받을 수 있음
myLogger.setRequestURL(requestURL);
myLogger.log("controller test");
LogDemoService.logic("testId"); // 이 부분이 문제입니다!!
return "OK";
}
}
그걸 토대로 LogDemoController를 살펴보시면
LogDemoService.logic("testId"); // 이 부분이 문제입니다!!
이 부분에서 logDemoService.logic("testId")
로 부르지 않고 LogDemoService.logic("testId")
로 부르고 있기 때문에 컴파일러는 너 왜 정적 메서드를 부르고 있냐? 이렇게 에러를 뱉어주고 있는 것으로 보입니다.
logDemoService.logic("testId")
로 고치고 나서 다시 한 번 시도해보시겠습니까?
감사합니다.
와 진짜 감사합니다!!! 부족한게 많은데 많이 배워갑니다😀