본문 바로가기

JAVA

make DI Framework by reflection

반응형

나만의 DI 프레임워크 만들기

 

@Inject 라는 애노테이션 만들어서 필드 주입 해주는 컨테이너 서비스 만들기

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

}

BookService.java

public class BookService {

	@Inject
	public Object bookRepository;

}

ContainerService.java

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 ) {
				Object fieldInstance = createInstance(f.getType());
				f.setAccessible(true);
				try {
					f.set(instance, fieldInstance);
				} catch ( IllegalAccessException  e) {
					e.printStackTrace();
				}
			}
		});
		
		return instance;
	}
	
	private static <T> T createInstance (Class<T> classType) {
		try {
			return classType.getConstructor(null).newInstance();
		} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException |SecurityException e) {
			e.printStackTrace();
		}
		return null;
	}
}

test

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);
		
	}
	
}
  • classType에 해당하는 타입의 객체를 만들어 준다.
  • 단, 해당 객체의 필드 중에 @Inject가 있다면 해당 필드도 같이 만들어 제공한다.

pom.xml

 
 <dependency>
 	<groupId>me.jueun</groupId>
    <artifactId>reflection.di.ex</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    </dependency>
</dependencies>

AccountRepository.java

public class AccountRepository {

	public void save() {
		System.out.println("Repo.save");
	}

}

AccountService.java

public class AccountService {

	@Inject
	AccountRepository accountRepository;
	
	public void join() {
		System.out.println("Service.join");
		accountRepository.save();
	}
}

App.java

public class App {
    public static void main( String[] args ) {

    	AccountService accountService = ContainerService.getObject(AccountService.class);
    	accountService.join();
    }
}

 

 

 

리플렉션 정리

리플렉션 사용시 주의할 것

  • 지나친 사용은 성능 이슈를 야기할 수 있다. 반드시 필요한 경우에만 사용할 것
  • 컴파일 타임에 확인되지 않고 런타임 시에만 발생하는 문제를 만들 가능성이 있다.
  • 접근 지시자를 무시할 수 있다.

스프링

  • 의존성 주입
  • MVC 뷰에서 넘어온 데이터를 객체에 바인딩 할 때

하이버네이트

  • @Entity 클래스에 Setter가 없다면 리플렉션을 사용한다.

JUnit

참고

 

반응형

'JAVA' 카테고리의 다른 글

[JAVA] try with resources  (0) 2020.11.06
jar, class 파일 확인하기  (0) 2019.12.02
Reflection  (0) 2019.09.29
byte code 조작  (0) 2019.09.28
Byte Code  (0) 2019.09.28