복붙노트

[SPRING] Field @Autowired의 마법은 무엇입니까?

SPRING

Field @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. ==============================

    1.@Autowired 필드를 갖는 아이디어는 의문의 대상입니다. 작동하지만 구현의 다른 측면 (예 : 테스트)은 어렵습니다.

    @Autowired 필드를 갖는 아이디어는 의문의 대상입니다. 작동하지만 구현의 다른 측면 (예 : 테스트)은 어렵습니다.

    주사에는 3 가지 유형이 있습니다.

    Inversion of Control (또는 Dependency Injection)의 아이디어 중 하나는 적절한 테스트 구현 지원을 제공하기 위해 코드 조각을 격리 할 수 ​​있다는 것입니다.

    좀 더 깊이 들어가기 위해서 단위 테스트 동안 클래스를 분리 된 형태로 원한다고 말할 필요가 있습니다. 클래스와 함께 사용할 것은 기본적으로 의존성 (주입)에 대한 모의입니다.

    결과는 무엇입니까?

  2. ==============================

    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>
    
  3. from https://stackoverflow.com/questions/31766028/what-is-the-magic-behind-field-autowired by cc-by-sa and MIT license