@Import 자세한 설명 및 @Import 개체를 주입하는 네 가지 방법

Java에서 @Import주석은 다른 구성 클래스나 Bean을 소개하는 데 사용되는 주석입니다. 이는 특정 구성 클래스나 빈을 Spring 컨테이너에 등록하고 이를 애플리케이션에서 사용할 수 있도록 하는 데 도움이 됩니다.

@Import에 대한 자세한 설명

  @Import@Configuration으로 주석이 달린 클래스나 일반 클래스에서 주석을 사용할 수 있습니다. @ImportResource, @ImportSelector의 다른 주석을 태그할 수 있는 메타 주석 역할을 합니다 @ImportBeanDefinitionRegistrar.

주석을 사용하면 @Import다음을 Spring 컨테이너로 가져올 수 있습니다.

  1. Configuration Class(Configuration Class): 다른 구성 클래스를 import하여 내부에 정의된 Bean을 컨테이너에 등록할 수 있다.
  2. 일반 클래스(비구성 클래스): 일반 클래스를 Spring 컨테이너에 Bean으로 가져옵니다.

@소스코드 가져오기


@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {

   /**
    * {@link Configuration @Configuration}, {@link ImportSelector},
    * {@link ImportBeanDefinitionRegistrar}, or regular component classes to import.
    */
   Class<?>[] value();

}
 

주석 관점에서 @Import 주석은 클래스에만 표시할 수 있으며 @Configuration 주석, ImportSelector, ImportBeanDefinitionRegistrar 또는 가져오기 일반 클래스와 함께 사용할 수 있습니다.

따라서 @Import를 사용하는 방법에는 클래스를 직접 가져오는 방법, Bean을 가져올 구성 클래스를 가져오는 방법, ImportSelector의 구현 클래스를 가져오는 방법, ImportBeanDefinitionRegister의 구현 클래스를 가져오는 방법이 있습니다. ImportSelector와 ImportBeanDefinitionRegistrar 두 인터페이스는 함께 사용하려면 @Import에 의존해야 하지만 @Import는 단독으로 사용할 수 있다는 점에 유의해야 합니다.

@Import의 구현 원칙

@Import주석의 구현 원리에는 구성 요소 검색, Bean 등록 및 Spring 프레임워크의 종속성 주입 메커니즘이 포함됩니다.

  1. 컴포넌트 스캐닝: Spring 프레임워크는 @Configuration컴포넌트 스캐닝 메커니즘을 통해 주석 또는 기타 지정된 주석이 있는 구성 클래스를 자동으로 스캔하고 로드하며 이를 구성 클래스로 인식합니다.

  2. 구성 클래스 등록: 구성 클래스가 인식되면 Spring은 이를 Bean으로 인스턴스화하고 컨테이너에 등록합니다. 이러한 방식으로 구성 클래스 내부에 정의된 모든 Bean은 Spring 컨테이너에서 관리될 수 있습니다.

  3. 주석 처리 : @Import구성 클래스에 @Import주석이 사용될 때 Spring은 주석의 매개변수를 구문 분석하고 다양한 유형의 매개변수에 따라 해당 처리를 수행합니다.

    • 다른 구성 클래스 가져오기: @Import매개변수가 다른 구성 클래스(예: @Configuration주석이 달린 클래스)인 경우 Spring은 가져온 구성 클래스를 컨테이너에 추가하므로 가져온 구성 클래스 내부에 정의된 Bean도 관리할 수 있습니다.

    • 일반 클래스 가져오기: @Import매개변수가 일반 클래스인 경우 Spring은 클래스를 Bean으로 인스턴스화하고 이를 컨테이너에 등록합니다.

    • 구현된 ImportSelector클래스 가져오기: @Import매개변수가 인터페이스를 구현하는 클래스인 경우 Spring은 인터페이스의 메소드를 ImportSelector호출 하고 반환된 클래스 이름 배열에 따라 해당 클래스를 Bean으로 등록합니다. 이런 방식으로 가져와야 하는 클래스를 특정 논리에 따라 동적으로 선택할 수 있습니다.ImportSelectorselectImports()

    • 구현된 ImportBeanDefinitionRegistrar클래스 가져오기: 매개변수가 인터페이스를 @Import구현하는 클래스 인 경우 Spring은 인터페이스의 메소드를 호출 하고 Bean 정의를 프로그래밍 방식으로 컨테이너에 등록합니다. 이러한 방식으로 사용자 정의 로직을 통해 추가 Bean을 등록할 수 있습니다.ImportBeanDefinitionRegistrarImportBeanDefinitionRegistrarregisterBeanDefinitions()

        위의 단계를 통해 주석을 사용하면 다른 구성 클래스, 공통 클래스 또는 인터페이스를 @Import구현하는 클래스를 쉽게 가져오고 이를 Spring 컨테이너에 등록하여 Bean 관리 및 종속성 주입을 수행할 수 있습니다.ImportSelectorImportBeanDefinitionRegistrar

임포트해야 하는 클래스


public class HelloImport {
  
    public void test() {
       System.out.println("hello JF");
    }
}

1. 수업을 직접 가져오기

@Import(HelloImport.class)
public class SpringTestApplication {

    public static void main(String[] args) {
        //1.通过AnnotationConfigApplicationContext创建spring容器,参数为@Import标注的类
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringTestApplication.class);
        HelloImport helloImport = applicationContext.getBean(HelloImport.class);
        elloImport.test();
    }
}

다음 방법은 프로젝트에서 일반적으로 사용됩니다.


@Import(HelloImport.class)
@Configuration
public class ConfigTest { 
}

2. 구성 클래스 가져오기 및 Bean 주입

@Configuration
public class HelloImportConfiguration {

    @Bean
    public HelloImport helloImport() {
        return new HelloImport();
    }
}

@Import(HelloImportConfiguration.class)
public class SpringTestApplication {

    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringTestApplication.class);
        HelloImport helloImport = applicationContext.getBean(HelloImport.class);
        helloImport.test();
    }
}

이 방법의 사용 시나리오는 구성 클래스를 직접 스캔할 수 없다는 것입니다.

3. ImportSelector 구현 클래스 가져오기

ImportSelector는 인터페이스이며 이 인터페이스를 구현하려면 selectImports 메서드를 다시 작성해야 합니다. selectImports 메소드는 컨테이너로 가져와야 하는 클래스의 정규화된 이름을 요소로 포함하는 문자열 배열을 반환합니다.


public class HelloImportSelector implements ImportSelector {
    /**
     * 返回需要导入的类名的数组,可以是任何普通类,配置类(@Configuration、@Bean、@CompontentScan等标注的类)
     * @importingClassMetadata:用来获取被@Import标注的类上面所有的注解信息
     */
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        List list = new ArrayList<>();
        list.add("intl.skw.test.HelloImport");
        return StringUtils.toStringArray(list);
    }
}

@Import(HelloImportSelector.class)
public class SpringTestApplication {

    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringTestApplication.class);
        HelloImport helloImport = applicationContext.getBean(HelloImport.class);
        helloImport.test();
    }
}

4. ImportBeanDefinitionRegistrar 구현 클래스 가져오기

클래스가 ImportBeanDefinitionRegistrar 인터페이스를 구현하면 레지스트리를 가져오고, 컨테이너에 Bean을 등록하고, Bean에 속성을 추가할 수 있습니다.

public class HelloImportDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(HelloImport.class)
                .getBeanDefinition();
        registry.registerBeanDefinition("HelloImport", beanDefinition);
    }
}

@Import(HelloImportDefinitionRegistrar.class)
public class SpringTestApplication {

    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringTestApplication.class);
        HelloImport helloImport = applicationContext.getBean(HelloImport.class);
        helloImport.test();
    }
}

추천

출처blog.csdn.net/Ascend1977/article/details/131391041