자바 커스텀 어노테이션 만들어서, 리플렉션 기술으로 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);
}
}
댓글