작성
·
725
0
안녕하세요.
강의 잘 보고 있는 수강생 입니다.
@Configuration과 proxyBeanMethods 강의를 듣고 실습하던 도중 질문이 있습니다.
Bean1, Bean2, Common, MyConfig 클래스들을 Static클래스로 만들어야 정상적인 테스트가 가능한것을 확인했는데요.
해당 클래스들을 정적 클래스가 아닌 내부 클래스로 작성하니 적절한 빈타입을 찾을 수 없다라는 에러메시지가 표출되었습니다.
이상해서 해당 클래스들을 별도의 java파일로 작성하니 문제없이 정상동작하는것을 확인하였는데요. 왜 내부클래스 작성 시 정적 클래스로 만들어야 동작하는지 이유를 잘 모르겠습니다. 감사합니다.
답변 2
5
좀 더 확인해서 정리된 내용을 말씀드릴게요.
아래 답변에 나와있듯이 내부 클래스는 외부 클래스의 인스턴스와 연결되어서 만들어져야 하기 때문에 단독으로 빈 오브젝트가 될 수 없습니다. 따라서 일반적으로 내부 클래스를 빈으로 등록할 수 없습니다.
그런데 내부 클래스가 빈이 되는 예외 경우가 있습니다. 이건 내부 클래스를 포함하고 있는 외부 클래스가 먼저 빈으로 등록이 되는 경우입니다. 이런 경우엔 내부 클래스의 인스턴스를 먼저 만들어진 외부 클래스의 빈 오브젝트와 연결해서 만들 수 있기 때문에, 스프링은 이런 경우에 한해서 내부 클래스로도 빈 등록이 가능하게 해줍니다. 외부 클래스가 @Component나 @Configuration인 경우에는 가능하겠죠. 이런 경우 내부 클래스로 만든 빈을 통해서 외부 클래스로 만든 빈의 내부 정보에 접근이 가능하긴한데.. 이렇게 굳이 만들 필요가 있을지는 모르겠습니다.
학습 테스트는 내부 클래스가 테스트 클래스에 정의되어있고 테스트 클래스는 빈 오브젝트로 등록되지 않으므로 그 안에 정의된 내부 클래스는 빈으로 등록이 되지 않는 것입니다.
와... 제가 작성한 글로 인해 강의까지!!!
작성하신 설명과 영상 둘다 보았습니다. 자바의 기본적인 질문인것 같아 질문 드릴때 고민이 되었는데 답변 주셔서 감사합니다!! 열심히 수강하도록 하겠습니다. 감사합니다👍
이번 강의에 대한 답변을 주셨지만 자바에 대한 공부도 같이 되는 좋은 답변이었던 것 같습니다. 혹시 이 답변과 유튜브에 올려주신 영상을 참고해서 블로그에 학습 과정을 포스팅해도 괜찮을까요? 출처는 반드시 남기겠습니다.
4
자바에서 내부 클래스는 정적 클래스일 수는 없습니다.
클래스 안에 다른 클래스를 정의하는 방법을 통틀어서 중첩(nested) 클래스라고 합니다.
중첩 클래스는 다시 정적 클래스와 내부 클래스로 나뉩니다. 두 가지는 다른 클래스 안에 중첩되어있다는 점을 제외하면 큰 차이가 있습니다.
우선 정적 클래스로 학습 테스트의 빈 클래스를 정의한 이유는 특별한 것은 아닙니다. Bean1, Bean2를 별도의 파일에 클래스로 만들어도 상관없습니다. 이걸 정적 중첩 클래스로 만든 이유는 간단한 클래스를 같은 파일 안에 정의해서 코드 읽기가 편하고, 관련이 깊은 클래스를 한 곳에 모아놓는 장점이 있기 때문입니다. 사실 정적 중첩 클래스는 그냥 별도의 파일에 정의된 탑레벨 클래스와 동일하다고 봐도 됩니다.
내부 클래스는 static이 아닌 중첩 클래스를 말하는 것인데, 이 내부 클래스의 가장 큰 특징은 자신을 포함하고 있는 클래스의 인스턴스와 연결되어서만 만들어진다는 것입니다. 그래서 외부 클래스의 인스턴스의 멤버 필드 등에도 바로 접근이 가능합니다. 반면 내부 클래스는 외부 클래스의 인스턴스가 존재하지 않으면 만들어질 수가 없습니다.
바로 이런 이유로 static이 아닌 중첩 클래스, 즉 내부 클래스는 그 자체로 빈을 만드는 클래스가 될 수가 없습니다. 외부 클래스의 인스턴스가 먼저 만들어져야지만, 만들 수 있는 클래스이고 외부 클래스의 인스턴스와 연결이 되어있야 하기 때문에 내부 클래스 자체로 독립적인 빈 오브젝트를 스프링이 만들 수 없기 때문입니다.
중첩되어있지만 일반 탑 레벨 클래스와 같은 성격을 가지는 중첩 정적 클래스는 스프링의 빈이 될 수 있습니다.
이와 같은 이유로 내부 클래스는 빈으로 생성이 되지 않는 것입니다. 내부 클래스의 특별한 케이스인 로컬 클래스나 익명 클래스도 같은 이유로, 그 자체로 빈 클래스로 정의될 수 없습니다. 물론 인스턴스를 만들어서 @Bean 팩토리 메소드에서 리턴한다면 그때는 빈으로 등록이 가능하겠지요.
중첩 클래스와 내부 클래스에 관련한 자바 문법 서적의 내용이나 관련 자료를 한번 찾아보시면 도움이 될 겁니다.
제가 추천하는 건 오라클 튜토리얼에 나온 다음 문서입니다.
https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html
중첩 클래스, 내부 클래스, 정적 중첩 클래스 등의 구분이 정확하게 구분해서 알고 있지 않으면 가끔 혼란을 줄 수있으니 이번 기회에 잘 정리해서 기억해두시면 좋겠습니다.
관련된 내용을 테스트를 좀 더 해봤습니다.
생각했던 것처럼 내부 클래스라고 무조건 빈 클래스로 사용될 수 없는 것은 아니네요. 이 부분은 좀 더 내용을 보강해서 다시 답글을 달아보겠습니다.
https://www.youtube.com/watch?v=2G41JMLh05U
질문하신 내용에 대한 설명을 담은 유튜브 영상을 하나 올렸습니다. 참고해보세요.