[SPRING] Field @Autowired의 마법은 무엇입니까?
SPRINGField @Autowired의 마법은 무엇입니까?
현재 스프링 지식을 향상시키고 있습니다. 필드에서 Spring 어노테이션 @Autowire를 사용할 때 실제로 어떤 일이 발생하는지 궁금합니다.
다음은 코드의 일부입니다.
OutputHelper 파일
@Component
public class OutputHelper {
@Autowired
@Qualifier("csvOutputGenerator")
private IOutputGenerator outputGenerator;
public void setOutputGenerator(IOutputGenerator outputGenerator) {
this.outputGenerator = outputGenerator;
}
// I can focus only on what my code do because my objects are injected
public void generateOutput(){
outputGenerator.generateOutput();
}
}
CsvOutputGenerator 파일
@Component
public class CsvOutputGenerator implements IOutputGenerator {
public void generateOutput(){
System.out.println("Csv Output Generator");
}
}
신청서 파일
public static void main(String[] args) {
// Create the spring context
ApplicationContext context = new ClassPathXmlApplicationContext("META-INF/spring/spring-module.xml");
// Get the configured OutpuHelper from the spring-module.xml
OutputHelper output = (OutputHelper) context.getBean("outputHelper");
// Display output from the output configured
output.generateOutput();
}
구성 파일에
이 코드를 실행하면 모든 것이 잘 동작합니다. 하지만 놀란 것은 OutPutHelper 파일에서 setOutputGenerator를 삭제하면 코드 조각이 계속 작동한다는 것입니다. 이 구성으로 OutputHelper를 처음에는 기본 생성자로 만들고 setter로 초기화했습니다.
변수 outputGenerator를 초기화 할 수 없으므로 오류가 예상됩니다.
누구든지 내가 이해하도록 도와 줄 수 있니?
해결법
-
==============================
1.@Autowired 필드를 갖는 아이디어는 의문의 대상입니다. 작동하지만 구현의 다른 측면 (예 : 테스트)은 어렵습니다.
@Autowired 필드를 갖는 아이디어는 의문의 대상입니다. 작동하지만 구현의 다른 측면 (예 : 테스트)은 어렵습니다.
주사에는 3 가지 유형이 있습니다.
Inversion of Control (또는 Dependency Injection)의 아이디어 중 하나는 적절한 테스트 구현 지원을 제공하기 위해 코드 조각을 격리 할 수 있다는 것입니다.
좀 더 깊이 들어가기 위해서 단위 테스트 동안 클래스를 분리 된 형태로 원한다고 말할 필요가 있습니다. 클래스와 함께 사용할 것은 기본적으로 의존성 (주입)에 대한 모의입니다.
결과는 무엇입니까?
-
==============================
2.사실, CDI는 java Reflection을 사용하여 필드에 액세스하므로 setter는 쓸모가 없습니다.
사실, CDI는 java Reflection을 사용하여 필드에 액세스하므로 setter는 쓸모가 없습니다.
즉, 메서드 호출을 통해 필드에 더 이상 액세스 할 수 없습니다. 리플렉션을 사용하면 클래스의 모든 필드를 반복하여 특정 특수 효과로 짜증나는지 확인할 수 있습니다.
이 경우, 클래스의 필드에 @Autowired (또는 J2E 유사 클래스 인 @Inject)가 표시되면 컨테이너는이 클래스에 대해 사용 가능한 Bean이 있으면 클래스 경로를 반복합니다.
컨텍스트가 시작되면 컨테이너는 클래스를 반복하고 @Inject 또는 @Autowired로 주석 된 모든 필드를 검색합니다.
이 필드의 경우 사용 가능한 빈을 검색합니다.
여기 간단한 예제가 필요하다.
public class SpringClassInChargeOfDependencyInjection { public void handdleInjections(T objectWithInjectableField) { Class<T> clazz = objectWithInjectableField.class; Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { if (field.isAnnotationPresent(Autowired.class) || field.isAnnotationPresent(Inject.class)) { //find a bean for the type; Object injectableBean = getAvailablebean(field.getType()); field.setAccessible(true); //inject the value into the class, this line explain why the setter is not necessary field.set(objectWithInjectableField, injectableBean); } } } }
이것은 작동 방식을 설명하기위한 비 작동 예제입니다.
Spring이 만든 @Autowired 대신 @Inject를 사용하면 inject는 JSR-330의 일부입니다. Spring은 @Inject도 이해한다. 프로젝트에 javax.inject jar 의존성을 추가하기 만하면된다.
<dependency> <groupId>javax.inject</groupId> <artifactId>javax.inject</artifactId> <version>1</version> </dependency>
from https://stackoverflow.com/questions/31766028/what-is-the-magic-behind-field-autowired by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] Oauth2 : 잘못된 액세스 토큰 (0) | 2019.07.19 |
---|---|
[SPRING] 'org.springframework.web.multipart.commons.CommonsMultipartFile'유형의 값을 필수 유형으로 변환하는 데 실패했습니다. (0) | 2019.07.19 |
[SPRING] 스프링 부트 2.0에서`@Endpoint (id = "health")`를 만드는 방법은? (0) | 2019.07.19 |
[SPRING] 콩에 대한 Spring @Configuration 캐시 참조는 어떻게 되는가? (0) | 2019.07.19 |
[SPRING] Spring 5.0.2의 Log4jConfigurer (0) | 2019.07.19 |