묻고 답해요
131만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결스프링 핵심 원리 - 고급편
포인트컷과 어드바이스의 관계를 다음과 같이 이해하면 될까요?
프록시대리자를 통칭디자인 패턴프록시 패턴접근 제어캐싱(Caching), 지연 로딩(Lazy Loading)검증(Valid), 인증(Auth)데코레이터 패턴부가 기능로깅(Log)컨버터(Convertor), 포맷터(Formatter)스프링 프록시포인트 컷검증(Filter)만 담당어드바이스검증 이외의 모든 로직을 담당데코레이터 패턴 + 프록시 패턴(캐싱, 지연 로딩)어드바이저포인트 컷 1개 + 어드바이스 1개의 묶음위와 같이 이해하는게 맞게 이해하고 있는지 궁금합니다.
-
미해결스프링 핵심 원리 - 고급편
쓰레드 로컬과 쓰레드 스택의 차이
동시성 문제를 해결하기 위해서 쓰레드 로컬이 각 쓰레드별 전용 저장공간을 만들어 데이터를 저장한다고 하셨는데 JVM의 메모리영역중에서 힙과 메소드영역은 모든 쓰레드가 공유하지만 각 쓰레드별로 스택공간이 할당된다고 알고 있습니다.그렇다면 쓰레드 로컬을 통해 데이터를 저장하면 각 쓰레드의 스택영역에 데이터가 저장되는 것인가요?만약 아니라면 쓰레드 로컬과 각 쓰레드의 스택영역에 저장되는 데이터들은 어떤 차이가 있는 것인지 궁금합니다.
-
미해결스프링 핵심 원리 - 고급편
강의를 듣다 문득, ThreadLocal과 synchronized의 성능차이?가 궁금하여서 질문했습니다.
안녕하세요. 영한님!! ThreadLocal 쪽강의를 듣다가 궁금하게 생겨 질문하게 되었습니다.java에서 동시성을 해결할 수 있는 방법 중 하나인 synchronized가 있다고 알고 있습니다.ThreadLocal과 비교해볼 때 성능적으로 큰 차이가 있을까요??? 혹은 코드 취향에 따라 선택적으로 사용하면 될지 문득 궁금하여 질문을 남겼습니다.
-
미해결스프링 핵심 원리 - 고급편
@target 적용 여부가 애플리케이션 로딩 이후에 결정되는 이유
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용]@target 의 동작 방식 자체는 이해가 되는데, @target 이 적용 여부가 애플리케이션 로딩 이후(빈이 모두 생성된 이후)에 결정되어야 하는 이유가 궁금합니다. 빈으로 등록될 객체가 생성된 직후, Spring 빈 후처리기가 동작할 때, 그 객체 클래스 및 상속 관계에 있는 클래스들에, 어떤 annotation 들이 달려있는지 판단 가능하다고 생각했습니다. 때문에, Spring 이 AspectJ Expression 사용 시 @target 조건만 주고 다른 조건으로 한정하지 않을 때, 모든 빈에 대해 proxy 를 생성하려 시도한다는 점이 잘 이해가 되지 않았습니다. 제가 뭔가 놓치고 있는 지점이 있는 것 같은데, 지적 부탁드립니다. 좋은 강의 감사합니다.
-
미해결스프링 핵심 원리 - 고급편
RequestMapping 설정이 안됩니다
https://drive.google.com/file/d/1ZzF_drL431el08VSflTR0Zldo9mG72n/view?usp=share_linkjava/com/exmple/aop/v2 폴더에 해당 실습 내용이 담겨있습니다.구체 클래스 기반 프록시를 강의와 동일하게 적용해 보았습니다. target에 RequestMapping을 설정했으나 실제로 적용이 되지 않았습니다. (혹시 몰라 proxy에도 설정했었지만 적용되지 않았습니다.)디버깅 해보면 /v2/request가 없는 거까진 확인했습니다.
-
해결됨스프링 핵심 원리 - 고급편
내부 호출에서 자기 자신 주입해도 여전히 오류가 뜹니다
프록시와 내부 호출 - 대안1 자기 자신 주입 파트 진행중입니다. 코드를 그대로 따라 쳤는데도 순환참조 오류가 계속 발생합니다. 뭔가 빠진걸까요..
-
해결됨스프링 핵심 원리 - 고급편
동시성 이슈 - 전략패턴
전략 패턴 - 예제 3 7:50초까지 듣고 질문 남깁니다.문맥(Context)에 로직(Strategy)을 담기 위해 두가지 방법을 알려주셨습니다.Context 필드에 Strategy 생성자 주입Context 메소드에 Strategy 위임(?) 1번 방식에서 생성자 주입시 Setter를 이용하여 필드의 전략을 바꿔서 실행하는 경우 '동시성 이슈'가 발생할 수 있다고 말씀하셨는데, 동시성 측면에서 2번과 차이가 있을까요?
-
미해결스프링 핵심 원리 - 고급편
클래스 기반 프록시에서
클래스 기반 프록시를 만들 때,프록시는 프록시 대상 클래스를 상속 받고, target을 주입 받아서 호출하는데어차피 프록시 대상 클래스를 상속 받아야한다면, 그냥 super.로직()을 호출하면 안되나요?그럼 target을 주입 받을 필요도 없어질텐데 혹시 이 방법은 왜 안되는지 궁금해서 질문 드립니다.
-
해결됨스프링 핵심 원리 - 고급편
[전략 패턴 - 예제 2] 코틀린으로 연습하는 중에 변환이 되지 않아 문의 드립니다.
// ContextV1Test.java @Test void strategyV3() { ContextV1 context1 = new ContextV1(new Strategy() { @Override public void call() { log.info("비즈니스 로직1 실행"); } }); context1.execute(); ContextV1 context2 = new ContextV1(new Strategy() { @Override public void call() { log.info("비즈니스 로직2 실행"); } }); context2.execute(); } @Test void strategyV4() { ContextV1 context1 = new ContextV1(() -> log.info("비즈니스 로직1 실행")); context1.execute(); ContextV1 context2 = new ContextV1(() -> log.info("비즈니스 로직2 실행")); context2.execute(); }// ContextV1Test @Test fun strategyV3() { val context1 = ContextV1(object : Strategy { override fun call() { log.info("비즈니스 로직1 실행") } }) context1.execute() val context2 = ContextV1(object : Strategy { override fun call() { log.info("비즈니스 로직2 실행") } }) context2.execute() } @Test fun strategyV4() { val context1 = ContextV1({ log.info("비즈니스 로직1 실행") }) context1.execute() val context2 = ContextV1({ log.info("비즈니스 로직2 실행") }) context2.execute() }interface 에 메서드가 하나만 있는 경우 람다를 활용할 수 있다. java 코드를 코틀린으로 변환하면서 v3 는 정상적으로 변환에 성공했습니다.하지만 v4 는 정상적으로 되지 않습니다.코틀린에 아직 익숙하지 않다보니 생긴 문제인거 같기도 한데..혹시 강의 범위를 벗어나긴 하지만 도움을 주실 수 있을까요?
-
해결됨스프링 핵심 원리 - 고급편
HelloTraceV1 주입하는이유
안녕하세요 제가 뭔가 기초가 부족한것 같긴한데 질문드립니다HelloTraceV1 구현체는 빈으로 등록해서 OrderControllerV1에 주입하는 이유가 무엇인가요??인터페이스라면 OCP원칙을 지킨다는이점으로 이해할수있는데 new로 생성하지않고 구현체를 직접 등록하는이유는 따로 있나요??이부분에선 OCP원칙이 아닌 스프링빈의 싱글톤,생명주기 관리 등의 이점을 얻기위해 인가요?? 혹은 훗날 HelloTraceV1이 변경될수있는 가능성을 염두하는건가요??
-
해결됨스프링 핵심 원리 - 고급편
쓰레드로컬관련 질문이 있습니다.
안녕하세요.수업을 듣다가 궁금하여 질문드립니다.. FiedlLogTrace는 빈으로 등록하여 작동하니, 동시성 문제가 있어 쓰레드 로컬을 사용하였는데 @Controller, @Service 이러한 것들도 빈으로 등록이 되는 것인데 이러한 것들은 동시성 문제와 관련이 없는건가요? 바보같은 질문이지만.. 감사합니다.
-
해결됨스프링 핵심 원리 - 고급편
args관련해서 질문있습니다!.
안녕하세요 항상 좋은 강의 감사합니다.전 강의 args와 현재 강의를 듣고 제가 이해를 잘 하지 못한 것 같아 질문 하나 드립니다.해당 강의에서 "args, @args, @target은 실제 객체 인스턴스가 생성 되고 실행될 때 어드바이스 적용 여부를 확인할 수 있다." 고 하셨습니다.1.전 강의 args에서는 spring을 통한 테스트가 아니었기 때문에 모든 스프링 빈에 AOP를 적용 하려는 것을 생각하지 않아도 되는게 맞을까요?2.args를 테스트 할때는 왜 스프링으로 빈 등록을 할 필요가 없었을까요?String, Object는 java.lang은 이미 가지고 있고, args(), args(..), args(*)등은 인스턴스 정보가 필요 없고 만약 Custom한 객체 args(Parent)같은 타입이 들어간다면 자동으로 스프링 동작이 필요한 걸까요?기초적인 질문이라 죄송합니다.
-
미해결스프링 핵심 원리 - 고급편
`..` 다음에 *.*을 하는 이유
안녕하세요. 코드를 따라치다가 한 가지 궁금한 점이 있습니다. 이전에 배우기로는 `..`는 하위 패키지를 포함하는 걸로 알고 있습니다. @Before("execution(* hello.aop.internalcall..*.*(..))") 위 코드 대신에 @Before("execution(* hello.aop.internalcall..*(..))") 이렇게만 만해도 충분하지 않나요? 1번처럼 작성하신 이유가 궁금합니다.
-
해결됨스프링 핵심 원리 - 고급편
@Import(AppV1Config.class) 질문있습니다.
안녕하세요. 강사님!한가지 궁금한 사항이 있어서 질문드립니다. 강의에서 필요한 컴포넌트만 스캔하기 위해서 hello.proxy.app 하위만 scanBasePackages로 설정해주셨는데 별개로 AppV1Config 클래스를 bean 으로 등록하기 위해서 ProxyApplication 클래스위에 @Import(AppV1Config.class)를 선언하셨었는데, 어떻게 AppV1Config 클래스가 독립적으로 빈으로 등록되는지 상세하게 알수있을까요? 공식 doc을 봐도 이해가 안되네요 ㅠㅠ AppV1Config 클래스에 적용된 @Configuration 어노테이션을 까보니 @Component 어노테이션이 적용되었지만, 애플리케이션 기동시에는 @SpringBootAppilcation 어노테이션의 scanBasePackages를 hello.porxy.app 하위로 적용했기 때문에 hello.proxy.config 하위에 있는 AppV1Config가 무시되지는 않나 싶어서요 공홈을 보니까 There's no problem in declaring all the configurations. But imagine the trouble to control dozens of configuration classes within different sources. There should be a better way. The @Import annotation has a solution, by its capability to group Configuration classes:이렇게 설명이 되어있는데 혹시 hello.proxy.app 하위로 컴포넌트 스캔을 할 경우 @Import에 있는 Configuration으로 등록되어 있는 AppV1Config 파일도 함께 grouping 되어서 스캔되는 원리일까요?
-
미해결스프링 핵심 원리 - 고급편
컨트롤러 프록시가 어떻게 호출되는지 잘 모르겠습니다
인터페이스에 GetMapping이 되어있고 이 인터페이스를 Impl 구현체와 프록시가 각각 구현하고 있는데 어떤 이유로 Impl이 아닌 프록시가 호출되는지 잘 모르겠습니다. 마찬가지로 구체클레스에 적용하는 V2도 OrderController가 아닌 이것을 상속받은 프록시가 호출되는 이유가 궁금합니다
-
미해결스프링 핵심 원리 - 고급편
@Around 오류
@Around에서 리턴값을 바꾸면 ClassCastException이 발생합니다. Controller에 aop를 적용해서 target controller는 String을 반환하게 했고 advice에서는 ResponseEntity를 반환하게 설정했는데요... 다음과 같은 오류가 발생합니다.. 디버깅을 찍어봐도 이유를 모르겠습니다. 원인이 무엇인지 알려주시면 감사하겠습니다!!! org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.ClassCastException: class org.springframework.http.ResponseEntity cannot be cast to class java.lang.String (org.springframework.http.ResponseEntity is in unnamed module of loader 'app'; java.lang.String is in module java.base of loader 'bootstrap') at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) at javax.servlet.http.HttpServlet.service(HttpServlet.java:655) at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:72) at javax.servlet.http.HttpServlet.service(HttpServlet.java:764) at org.springframework.mock.web.MockFilterChain$ServletFilterProxy.doFilter(MockFilterChain.java:167) at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:134) at org.springframework.test.web.servlet.MockMvc.perform(MockMvc.java:199) at com.github.rere950303.apiutil.aspect.ResponseApiAspectTest.methodName(ResponseApiAspectTest.java:71) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725) at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60) at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131) at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149) at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140) at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84) at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115) at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105) at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106) at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64) at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45) at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37) at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104) at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141) at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138) at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95) at java.base/java.util.ArrayList.forEach(ArrayList.java:1541) at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141) at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138) at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95) at java.base/java.util.ArrayList.forEach(ArrayList.java:1541) at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141) at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138) at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95) at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35) at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57) at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52) at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114) at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86) at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86) at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53) at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71) at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38) at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11) at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35) at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235) at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)Caused by: java.lang.ClassCastException: class org.springframework.http.ResponseEntity cannot be cast to class java.lang.String (org.springframework.http.ResponseEntity is in unnamed module of loader 'app'; java.lang.String is in module java.base of loader 'bootstrap') at com.github.rere950303.apiutil.aspect.ResponseApiAspectTest$TestController$$EnhancerBySpringCGLIB$$8953dbd8.test2(<generated>) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150) at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ... 78 more
-
해결됨스프링 핵심 원리 - 고급편
target 인스턴스도 빈으로 등록은 되는 건가요?
강의를 재밌게 보고 있는데, 의문이 있어서 질문드립니다. "대안1 자기 자신 주입" 강의 0:47 때 그림을 보여주시는데, 해당 그림에서는 target 인스턴스 내에서 proxy 를 의존성 주입 받아서 사용하는 걸로 표현됩니다. 여기서 의문이 들었습니다. 제 지식으로는 "스프링 빈으로 proxy 가 등록되고, target 은 빈으로 등록되지 않고, proxy 가 내부에서 참조만 한다"라고 알고 있습니다.(틀리다면 꼭 지적해주십쇼!) 그리고 또 한가지는 제가 알기로는 "의존성 주입을 위해서는 쓰는 쪽과, 받는 쪽 모두 빈으로 등록되어 있어야 한다."라는 것입니다. 이 두 가지 생각을 합치니 0:47 에 나오는 그림이 이상해 보였습니다. 그림 상에서는 빈으로 등록되지 않은 target 인스턴스가 의존성 주입을 받고 있는 걸로 보이거든요... 그림 처럼 되려면 target 인스턴스도 빈으로 등록이 되어야 하는데... 혹시 target 인스턴스도 빈으로 등록이 된건가요??
-
미해결스프링 핵심 원리 - 고급편
Advisor의 빈 저장소 등록 시점이 빈 처러기의 대상이 될 객체의 빈 저장소 등록 시점 보다 어떻게 더 빠를 수 있나요?
1. 생성: 스프링이 스프링 빈 대상이 되는 객체를 생성한다. ( @Bean , 컴포넌트 스캔 모두 포함)2. 전달: 생성된 객체를 빈 저장소에 등록하기 직전에 빈 후처리기에 전달한다.3. 모든 Advisor 빈 조회: 자동 프록시 생성기 - 빈 후처리기는 스프링 컨테이너에서 모든 Advisor 를 조회한다.4. 프록시 적용 대상 체크: 앞서 조회한 Advisor 에 포함되어 있는 포인트컷을 사용해서 해당 객체가 프록시를 적용할 대상인지 아닌지 판단한다. 이때 객체의 클래스 정보는 물론이고, 해당 객체의 모든 메서드를 포인트컷에 하나하나 모두 매칭해본다. 그래서 조건이 하나라도 만족하면 프록시 적용 대상이 된다. 예를 들어서 10개의 메서드 중에 하나만 포인트컷 조건에 만족해도 프록시 적용 대상이 된다. 제가 이해한 바로는 3.에서 스프링 컨테이너에 Advisor들은 이미 스프링 컨테이너에 등록 되어있는 것을 찾아오고 빈 후처리기에서 Advisor를 적용하여 프록시 객체를 생성할 target객체들은 생성만 되어있고 스프링 컨테이너에는 등록이 안되어 있는 것으로 이해했습니다. 이렇게 되려면 스프링이 Advisor를 구분해서 먼저 스프링 컨테이너에 등록 할 수 있어야 할 것 같은데 제가 제대로 생각하고 있는 것이 맞을까요?
-
해결됨코딩으로 학습하는 GoF의 디자인 패턴
팩토리 메소드 패턴이 커맨드 패턴을 이용해서 만든 패턴이라고 볼 수 있을까요?
- 학습 관련 질문을 남겨주세요. 상세히 작성하면 더 좋아요! - 먼저 유사한 질문이 있었는지 검색해보세요. - 서로 예의를 지키며 존중하는 문화를 만들어가요. - 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요. 안녕하세요 기선님, 항상 강의 잘듣고 있습니다. 다름이 아니고 커맨드 패턴 코드를 보다보니 팩토리 메소드 패턴에서 봤던 코드와 유사한 느낌이 들었는데 혹시 팩토리 메소드 패턴이 커맨드 패턴을 사용해서 만들었다고 볼 수 있을까요??
-
해결됨스프링 핵심 원리 - 고급편
Junit Test 에서 setDaemon(true) 를 안했어도 테스트 코드가 종료되는 이유가 뭘까요?
안녕하세요. "동시성 문제-예제코드" 강의 07:35 쯤에 나오는 설명과 실행결과가 이해가 안되서 질문드립니다. 제가 알기로는 메인 쓰레드가 종료가 되더라도, Thread thread = new Thread(); thread.setDaemon(true); 처럼 하지 않으면 프로그램이 끝나지 않는 걸로 알고 있습니다. 그런데 Junit Test 내에서는 thread.setDaemon(true)를 안 했음에도 그냥 테스트 코드가 종료되버립니다. 대체 이렇게 동작하는 원인이 뭘까요?