반응형
리플렉션
: 컴파일 된 자바 코드에 역으로 클래스를 불러 메소드 및 필드 정보를 구해오는 방법
JVM에서 실행되는 애플리케이션의 런타임 동작을 검사하거나 수정할 수 있는 기능이 필요한 경우 사용
스프링 프레임워크, 마이바티스, 하이버네이트 등의 라이브러리에서 사용
Reflection을 사용해서 스프링에서는 런터임 시 개발자가 등록한 빈을 애플리케이션 내에서 사용 할 수 있음
Reflection 주의사항
1) 오버헤드 발생 : 성능 저하를 발생시킬 수 있기 때문에 성능에 민감한 애플리케이션에서는 사용하지 않음
2) 캡슐화 저해 : private로 설정한 member에 접근 가능하기 때문에 코드 기능이 저하되며 여러 가지 문제가 발생
방법 1. class 문법을 이용하여 Class 타입의 인스턴스를 생성
: Class 타입의 인스턴스는 해당 클래스의 메타 정보를 가지고 있는 클래스
Class class1 = Account.class;
System.out.println(class1);
출력 결과
class com.greedy.section02.reflection.Account
방법 2. object 클래스의 getClass() 메소드를 이용하여 Class 타입으로 리턴 받아 사용
Class class2 = new Account().getClass();
System.out.println(class2);
출력 결과
class com.greedy.section02.reflection.Account
TYPE 필드를 이용하여 원시형 클래스를 반환 받을 수 있음
Class class8 = Double.TYPE;
System.out.println(class8);
Class class9 = Void.TYPE;
System.out.println(class9);
방법 3. Class.forName() 메소드를 이용하여 런타임 시 로딩을 하고 그 클래스 메타 정보를 Class 타입으로 반환 받을 수 있음
try{
Class class3 = Class.forName("com.greedy.section02.reflection.Account");
System.out.println(class3);
=> class com.greedy.section02.reflection.Account
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
클래스 메타 정보를 이용하여 여러가지 정보를 반환 받는 메소드
1) getSuperclass()
: 상속 된 부모 클래스 반환
Class superClass = class1.getSuperclass();
System.out.println(superClass);
=> class java.lang.Object
상속 관계가 없는 class는 Object class반환
2) getDeclaredFields();
: 필드 정보 반환
import java.lang.reflect.Field;
Field[] fields = Account.class.getDeclaredFields();
for(Field field : fields){
필드로 부터 접근제한자, 타입, 이름 알아오기
System.out.println("modifiers: " + Modifier.toString(field.getModifiers())
+ ", type : " + field.getType()
+ ", name : " + field.getName());
}
출력 결과
modifiers : private, type : class java.lang.String, name : bankCode
modifiers : private, type : class java.lang.String, name : accNo
modifiers : private, type : class java.lang.String, name : accPwd
modifiers : private, type : int, name : balance
3) getConstructors() , getParameterTypes()
: 생성자 정보와 파라미터 타입 반환
Constructor[] constructors = Account.class.getConstructors();
for(Constructor con : constructors) {
System.out.println("name : " + con.getName());
Class[] params = con.getParameterTypes();
for(Class param : params) {
System.out.println("paramType : " + param.getTypeName());
}
}
출력 결과
name : com.greedy.section02.reflection.Account
paramType : java.lang.String
paramType : java.lang.String
paramType : java.lang.String
paramType : int
name : com.greedy.section02.reflection.Account
paramType : java.lang.String
paramType : java.lang.String
paramType : java.lang.String
name : com.greedy.section02.reflection.Account
4) getMethods()
: 메소드 정보 반환
Method[] methods = Account.class.getMethods();
Method getBalanceMethod = null;
for(Method method : methods) {
System.out.println(Modifier.toString(method.getModifiers()) + " "
+ method.getReturnType().getSimpleName()+ " "
+ method.getName());
if("getBalance".equals(method.getName())) {
getBalanceMethod = method;
}
}
출력 결과
public String withDraw
public String deposit
public String getBalance
public final native void wait
public final void wait
public final void wait
public boolean equals
public String toString
public native int hashCode
public final native Class getClass
public final native void notify
public final native void notifyAll
5) 생성자를 이용하여 인스턴스 생성
try { //constructors[생성자 정보 반환시 순번]
Account acc = (Account)constructors[0].newInstance("20","110-223-123456","1234", 10000); //Account 타입으로 다운 캐스팅
System.out.println(acc.getBalance());
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException
| InvocationTargetException e) {
e.printStackTrace();
}
출력 결과
110-223-123456 계좌의 현재 금액은 10000원 입니다.
6) invoke 메소드로 메소드 호출
try {//기본생정자를 통해서 객체 생성, 넘겨줄 값이 없기 때문에 null
System.out.println(getBalanceMethod.invoke((Account)constructors[2].newInstance(),null));
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException
| InstantiationException e) {
e.printStackTrace();
}
출력 결과
null 계좌의 현재 금액은 0원 입니다.
사용된 Account Class
package com.greedy.section02.reflection;
public class Account {
private String bankCode;
private String accNo;
private String accPwd;
private int balance;
public Account() {}
public Account(String bankCode, String accNo, String accPwd) {
super();
this.bankCode = bankCode;
this.accNo = accNo;
this.accPwd = accPwd;
}
public Account(String bankCode, String accNo, String accPwd, int balance) {
this(bankCode,accNo,accPwd);
this.balance = balance;
}
public String getBalance() {
return accNo + " 계좌의 현재 금액은 " + balance +"원 입니다.";
}
public String deposit(int money) {
String str = "";
if(money >= 0) {
balance += money;
str = money + "원이 입금 되었습니다.";
}else {
str = "금액을 잘 못 입력했쓔!!!";
}
return str;
}
public String withDraw(int money) {
String str = "";
if(balance >= money) {
balance -= money;
str = money + "원이 출금 되었습니다";
}else {
str = "잔액이 부족합니다. 잔액을 확인해주세요!";
}
return str;
}
}
반응형
'프로그래밍 > Spring & Spring boot' 카테고리의 다른 글
[Spring / 스프링] Spring Framework 의 특징과 구성모듈 (0) | 2022.09.05 |
---|---|
[Spring/스프링] CGLib 방식으로 Proxy 구현하기 (0) | 2022.09.05 |
15 Spring : @Aspect , @Before , @AfterAdvice, @AfterReturning, @AfterThrowing, @Around 사용하기 (0) | 2022.09.02 |
14 Spring : @Pointcut 어노테이션 표현식 (0) | 2022.09.02 |
13 Spring : AOP 개념 정리 (0) | 2022.09.02 |