1. java Reflection API
클래스 정보를 얻을 수 있는 기능을 제공
실행 중에 객체 생성, 메서드 호출 등을 가능하게 한다.
정적: 컴파일때 결정 new Car()
동적: 실행 중에 결정
Class animalClass = Animal.class // Animal 클래스 객체 얻기(클래스 자체의 객체)
Animal animal = (Animal)animalClass.newInstance();// 해당 Animal 클래스의 객체 생성
//즉, Class 객체를 얻어 newInstance()를 통해 실제 해당 클래스의 객체를 생성할 수 있다.
Method[] methodArr = animalClass.getDeclaredMethods(); // 클래스에 선언된 메서드 얻기
Field[] mvArr = animalClass.getDeclaredFields(); //클래스에 선언된 필드(iv,cv) 얻기
//만약 getMethods()를 호출할 경우 내가 지정하지 않는 상속 받은 모든 메서드를 보여준다.
//animal 클래스에서 setCloth(Cloth cloth) 매개변수를 가진 메서드 정의
Method method = animalClass.getMethod("setCloth",Cloth.class) //setCloth(Cloth cloth)
//해당 메서드를 통해 실행한다. 이때 해당 객체 animal의 setCloth(new Cloth)가 된다.
method.invoke(animal, new Cloth) // animal.setCloth(new Cloth)
Annotation[] annoArr = mvArr.getDeclaredAnnotations(); // 필드에 붙은 애너테이션 얻기
2. Class 객체
Class클래스의 객체, 클래스당 1개만 존재(싱글톤이다. 클래스 객체는 일반 객체와 달리 변화가 없음. 한개의 클래스 객체가 여러개일 필요도 없음. 그래서 싱글톤인 거 같다)
해당 클래스의 정보 조회, 객체 생성 등 의 기능 제공
클래스 파일(*.class)이 메모리에 로드될때 생성
card.java -> 컴파일 -> Card.class -> ClassLoader -> class 객체(사용하기 편함)
자바 코드가 컴파일 되어 class 파일이 된다. class 파일은 기계어로 되어 있고 이는 OS가 해석할 수 있도록 돕는다.
해당 class 파일은 ClassLoader라는 메모리에 올라가서 안전한지 악성코드가 없는지 확인 그리고 통과가 되면
class가 객체가 된다.
class를 객체로 만든 이유는 편하게 사용하기 위해서이다.
class 객체를 얻는 3가지 방법
Class classObj = Card.class // 1. 클래스 리터럴로 얻는 방법
Class classObj = new Card().getClass(); // 2.객체에서 얻는 방법
Class classObj = Class.forName("패키지.Card") //3. 클래스 이름으로 얻는 방법
public class ReflectionDi2 {
public static void main(String[] args) throws Exception{
//클래스 객체 만들기
//1. 클래스명.class
Class fruitClass1 = Fruit.class;
//2. 생성자.getClass()
Class fruitClass2 = new Fruit().getClass();
//3. Class.forName("패키지명.클래스명");
Class fruitClass3 = Class.forName("com.example.demo.di1.Fruit");
//매서드 배열 호출
//1. Method[] 배열로 받는다.그리고 변수의 값으로 -> 클래스 객체.getDeclaredMethods();
Method[] fristMethod = fruitClass1.getDeclaredMethods();
//실행
for(Method method : fristMethod){
System.out.println("method = " + method);
}
//실제 매서드 실행
//1. 객체생성
Fruit fruit = (Fruit) fruitClass1.newInstance();
//2. 매서드 뽑기: 클래스객체.getMethod("매서드 이름", "매개변수")
Method fruitNameMethod = fruitClass1.getMethod("setName", String.class);
//3. 매서드 실행 : 매서드.invoke(설정한 객체, 매개변수 값)
fruitNameMethod.invoke(fruit,"열대과일");
System.out.println(fruit.name); // 열대과일
//클래스의 직접 지정한 필드 배열로 받기
Field[] fruitFields =fruitClass1.getDeclaredFields();
System.out.println("Arrays.toString(fruitFields) = " + Arrays.toString(fruitFields));
//클래스의 public fleid만 가져오기
Field[] fruitFields2 = fruitClass2.getFields();
System.out.println("Arrays.toString(fruitFields2) = " + Arrays.toString(fruitFields2));
//클래스의 필드마다에 어노테이션 꺼내기
Fruit fruit1= new Fruit();
for(Field field : fruitFields){
Annotation[] annotations = field.getDeclaredAnnotations();
for(Annotation annotation : annotations){
if(annotation.annotationType() == Autowired.class){
String methodName = "set"+StringUtils.capitalize(field.getName());
Method method = fruitClass1.getMethod(methodName,String.class);
method.invoke(fruit1,"파파야");
}
}
}
System.out.println("fruit1.name = " + fruit1.name); // 파파야
}
}
'spring' 카테고리의 다른 글
Spring DI(1) (0) | 2023.07.02 |
---|---|
URL 인코딩 (0) | 2023.05.11 |
HttpServletRequest 요청 값 받는 다양한 방법 (0) | 2023.02.01 |
Http Requset /Response (0) | 2023.01.16 |
스프링 @Controller 사용법 (0) | 2023.01.15 |
댓글