2022.01.13 TIL

서승원·2022년 1월 13일
0

TIL

목록 보기
53/68
post-thumbnail

모델2 아키텍쳐를 이용한 게시판 코딩 방법의 또 다른 기법들을 알아봤다.
먼저 기존 이용하던 가변 파라미터를 이용해 Method로부터 invoke를 이용하는 방법이 아닌 배열을 이용한 방법이다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Temp530 {
    public void apple( A t , B j) {
        System.out.println"apple " + t + "," + j );
    }
}
public class Test530 {
    public static void main( String[] args ) throws Exception {
        Class<?> cls = Class.forName("banana.Temp530");
        Object obj = cls.newInstance();
        
        Method mtd = cls.getMethod( "apple", A.class, B.class );
        mtd.invoke( obj,  null , null );
        
        // -----------------------------------------------------
        // 1. 가변 파라미터를 이용한 호출 , 2. 배열을 이용한 호출
        
        Class<?>[] ptypes = new Class<?>[2];
        ptypes[0= A.class;
        ptypes[1= B.class;
        Method mtd2 = cls.getMethod("apple", ptypes );
        
        Object[] params = new Object[2];
        params[0= null;
        params[1= new B();
        
        mtd2.invoke( obj , params ); 
    }
}
cs

Test530의 윗부분은 기존의 방법이고, 아랫부분은 배열을 이용한 다른 방법이다. apple에 맞춰 2개짜리 배열 ptypes 를 만들고 각각에 매개변수인 A와 B의 Class 를 대입한다. 그리고 위의 방법에서 class 를 직접 입력한 것과 다르게 대입된 배열을 그대로 입력한다. 그리고 매개변수의 class에 맞도록 인스턴스를 생성해 Object의 배열에 대입하고 getMethod한 mtd2의 .invoke에 매개변수로 사용해서 함수를 호출한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class Temp531 {
    public void apple( B t , A j) {
        System.out.println"apple " + t + "," + j );
    }
}
public class Test531 {
    public static void main( String[] args ) throws Exception {
        Class<?> cls = Class.forName("banana.Temp531");
        Object obj = cls.newInstance();
        
        Method[] mtds = cls.getMethods();
        for( Method mtd : mtds ) {
            if( mtd.getName().equals("apple") ) {
                // System.out.println( mtd );
                Class<?>[] ptypes = mtd.getParameterTypes();
                for( Class<?> ptype : ptypes) {
                    System.out.println( ptype );
                }
                
                Object[] params = new Object[ ptypes.length ];
                forint i = 0 ; i < ptypes.length ; i++ ) {
                    if( ptypes[i] == A.class ) {
                        params[i] = new A();
                    }
                    else if( ptypes[i] == B.class ) {
                        params[i] = new B();
                    }
                }
                mtd.invoke( obj, params );
            }
        }
    }
}
cs
해당 방법을 이용해서 만든 Test531.java이다. 핵심이 되는 것은 ptypes 와 params 두 배열이다. ptypes에 대상이 되는 함수가 갖는 매개변수의 형식을 담고, params에 대입하게 될 매개변수를 담아서 함수 호출을 하도록 한다. 이 코드에서는 ptypes 배열을 for문으로 반복하여 A,B 두 클래스와 비교해서 알맞은 인스턴스를 params에 대입하도록 했다.


다음과 같이 for 문에서 ptypes에서 비교되는 결과에 따라 params의 배열이 가리키고 있는 항목 중에서 대입될 인스턴스가 결정되고, 매개변수로 삼아 apple을 호출하게 된다.

RequestParam

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
class Temp532 {
    public void apple( B j , @Param("X") A t, @Param("Z") Integer k ) {
        System.out.println"apple " + t + "," + j );
    }
}
public class Test532 {
    public static void main( String[] args ) throws Exception {
        Class<?> cls = Class.forName("banana.Temp532");
        Object obj = cls.newInstance();
        
        Method[] mtds = cls.getMethods();
        for( Method mtd : mtds ) {
            if( mtd.getName().equals("apple") ) {
                System.out.println( mtd );
                
                Class<?>[] ptypes = mtd.getParameterTypes();
                Annotation[][] pas = mtd.getParameterAnnotations();
                // 각 매개변수별 어노테이션의 갯수
                System.out.println( pas[0].length );
                System.out.println( pas[1].length );
                System.out.println( pas[2].length );
                //두번째로 선언된 A t 앞에 어노테이션이 적용됐는지 ?
                forint i = 0 ; i < pas[1].length ; i++ ) {
                    System.out.println( pas[1][i] );
                    System.out.println( pas[1][i].annotationType() == Param.class );
                // 어노테이션의 값 추출하기    
                    Param temp = (Param)pas[1][i];
                    System.out.println( temp.value() );
                }
                Param annot = (Param)getAnnotationInParam( mtd, 2, Param.class );
                System.out.println( annot.value() );
                Param annot2 = (Param)getAnnotationInParam( mtd, 0, Param.class );
                System.out.println( annot2.value() );
            }
        }
    }
    public static Annotation getAnnotationInParam( Method mtd , int idx, Class<?> annot ) {
        Annotation[][] pas = mtd.getParameterAnnotations();
        forint i = 0 ; i < pas[idx].length ; i++ ) {
            if( pas[idx][i].annotationType() == annot ) {
                return pas[idx][i];
                
            }
        }
        return null;
    }
}
cs
어노테이션을 이용한 방법인데, 함수, 클래스 자체에 어노테이션을 붙이는 걸 넘어서 매개변수에 어노테이션을 붙였다. @Param이라는 어노테이션에 매개변수 t와 k 에 각각의 value가 주어졌다. 역시 mtds 배열에 getMethods를 이용해 Temp532에 포함된 method 들을 대입하고, mtds 중 apple이라는 이름을 갖는 method를 if문을 통해 뽑아낸다. 위의 방법처럼 ptypes 배열을 만들어 변수 타입을 대입한다. 그리고 여기서 getParameterAnnotations 를 이용해 apple 함수의 매개변수들이 가지는 Annotation 들 역시 이용할 수 있다. 해당 함수의 return을 Annotation의 배열의 배열에 대입하고.매개 변수 별 어노테이션의 개수를 출력해봤다. 입력한대로 j는 0, t 는 1, k는 1 이 출력됐다. 그리고 어노테이션의 타입을 비교해보고 출력까지 해봤다. Param temp 에 pas 배열의 원하는 값을 대입한 후 , .value 를 이용해 출력했다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@RequestMapping("/del2.do3")
    public String del2( @RequestParam("no"String no ) throws Exception 
    {
            if( no == null || no.equals("")) {
            return "redirect:list.do?ecode=invalid_no";
        }
        
        Bang06DAO dao = new Bang06DAO_MariaImpl();
        
        Bang06VO po = new Bang06VO();
        po.setNo( Integer.parseInt(no) );
        Bang06VO vo = dao.findByPK(po);
        int uc = dao.delByPK(po);
        
        if( uc > 0 && vo.getFsn() != null ) {
            File file = new File( Util.uploadDir() + vo.getFsn() );
            if( file.exists() ) {
                file.delete();
            }
        }
 
        return "redirect:list.do3";    
    }
cs
이 방법을 활용해 del2 함수를 RequestParam 어노테이션을 활용해서 수정했다. 어노테이션을 통해 매개변수를 입력했기 때문에 getParameter 함수를 이용해 no에 직접 대입하여 사용할 필요가 없어진다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
else
                    {
                        RequestParam rp = (RequestParam)getAnnotationInParam( mtd, i ,                                             RequestParam.class );
                        if( rp != null )
                        {
                            String pn = rp.value();
                            if( ptypes[i] == String.class ) {
                                params[i] = request.getParameter(pn);
                            }
                            else if( ptypes[i] == Integer.class ) {
                                try {
                                    params[i] = Integer.parseInt( request.getParameter(pn) );
                                }
                                catch( Exception e ) {
                                    params[i] = null;
                                }
                            }
                            continue;
                        }
                    }
cs
해당 함수의 호출을 하는 방법이다. RequestParam 으로부터 어노테이션의 value를 가져와 params 배열에 대입하여 params를 invoke에 사용할 수 있게 했다.
profile
2년차 백엔드 개발자, crimy

0개의 댓글