Spring Boot

어노테이션 생성해서 Bean 컨테이너 생성 자체 관리하기

SH.DevBlog 2024. 1. 10. 18:39

# 어노테이션 생성

  • 어노테이션은 아래와 같이 생성하면 된다.
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE , ElementType.METHOD})
@Import(ImportsBeanSelector.class)
public @interface EnableBizHelper {

}

# Retention (어노테이션의 생명주기를 담당)

  • RetentionPolicy.SOURCE
    • 소스 코드(.java)까지 남아있는다.
    • 컴파일해서 .java -> .class 로 변경되면 .class에서는 해당 어노테이션이 사라지고 어노테이션에 해당하는 소스가 생성 될 것이다.(예시 : @Getter)
  • RetentionPolicy.CLASS
    • 클래스 파일(.class)까지 유지된다.(=바이트 코드)
    • 런타임 시에는 어노테이션이 사라진다. (예시 : @NonNull)
  • RetentionPolicy.RUNTIME
    • 런타임까지 유지된다. (계속 유지되는 것을 의미함)

# Import

  • 특정 클레스를 import할 때 사용하는 어노테이션(스프링 진영에서 제공해줌)

# 소스 구성

  • 'DeferredImportSelector'는 모든 @Configuration 빈이 처리된 후에 실행되는 클레스로써 특정 조건에 따라 Bean Container로 관리해야 하는 경우에 유용하게 활용할 수 있는 인터페이스이다.
  • 사용한 소스는 아래와 같다.
 
public class ImportsBeanSelector implements DeferredImportSelector {

    private final ClassLoader classLoader ;

    public ImportsBeanSelector(ClassLoader classLoader) {
        this.classLoader = classLoader;
    }

    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {

        Map<String , Object> methodM = importingClassMetadata.getAnnotationAttributes(EnableBizHelper.class.getName()) ;
        ImportCandidates importCandidates = ImportCandidates.load(EnableBizHelper.class, classLoader) ;
        List<String> autoConfigs = new ArrayList<>() ;

        for(String candidate : importCandidates) {
            autoConfigs.add(candidate) ;
        }

        return autoConfigs.stream().toArray(String[]::new) ;

    }
}

 

  • ImportCandidates.load 메소드를 들어가보면 아래와 같은 소스가 있는데, 하단의 프로젝트 경로와 같이 구성하면 해당 패키지 경로에 있는 Class 파일을 읽어와 스프링 Bean으로 등록할 수 있다.
public final class ImportCandidates implements Iterable<String> {

    private static final String LOCATION = "META-INF/spring/%s.imports";