본문 바로가기
카테고리 없음

간단한 DI 프레임워크 만드는 예제

by 문자메일 2022. 12. 18.

자바 커스텀 어노테이션 만들어서,  리플렉션 기술으로 instance 만드는 예제 소스코드

 

아래 소스코드 추가 설명 적자면

classType.getDeclaredFields()에서 지정한 클래스의 Field 값 전부 리스트로 가져온다.

if(f.getAnnotation(Inject.class) != null)로 해당 Field 위에 특정한 Annotation이 붙어 있는지 확인하고

붙어 있다면 f.getType() 메서드로 field의 Type 정보를 가져와서 인스턴스를 동적으로 생성하여 

f.set(instance, fieldInsatance) 명령으로 생성한 인스턴스를 부모 인스턴스에 set 하는 로직 수행한다.

 

ContainerService.java

package org.example.di;

import java.util.Arrays;

public class ContainerService {

    public static <T> T getObject(Class<T> classType){
        T instance = createInstance(classType);
        Arrays.stream(classType.getDeclaredFields()).forEach(f->{
            if (f.getAnnotation(Inject.class) != null){
                try {
                    Object fieldInstance = createInstance(f.getType());
                    f.setAccessible(true);
                    f.set(instance, fieldInstance);
                } catch (IllegalAccessException e) {
                    throw new RuntimeException(e);
                }
            }
        });

        return instance;
    }

    private static <T> T createInstance(Class<T> classType){
        try{
            return classType.getConstructor(null).newInstance();
        } catch (Exception e){
            throw new RuntimeException(e);
        }
    }
}

 

Inject.class

package org.example.di;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface Inject {
}

 

 

BookRepository.class

package org.example.di;

public class BookRepository {
}

 

BookService.class

package org.example.di;

public class BookService {

    @Inject
    BookRepository bookRepository;
}

 

ContainerServiceTest.class

package org.example.di;

import org.junit.Test;

import static org.junit.Assert.*;

public class ContainerServiceTest {

    @Test
    public void getObject_BookRepository(){
        BookRepository bookRepository = ContainerService.getObject(BookRepository.class);
        assertNotNull(bookRepository);
    }

    @Test
    public void getObject_BookService(){
        BookService bookService = ContainerService.getObject(BookService.class);

        assertNotNull(bookService);
        assertNotNull(bookService.bookRepository);
    }
}

댓글