jdk 와 cglib 에이전트 차이

에이전트 모드
원본 주소:http://www.cnblogs.com/ygj0930/p/6542259.html
 
1:프 록 시 모드(정적 프 록 시)
프 록 시 모드 는 자주 사용 하 는 디자인 모델 의 하나 로 우리 가 소프트웨어 디자인 을 할 때 자주 사용 하 는 프 록 시 는 보통 정적 프 록 시,즉 코드 에서 명시 적 으로 지정 한 프 록 시 를 말한다.정적 대 리 는 업무 실현 류,업무 대리 류 두 부분 으로 구성 된다.업무 실현 류 는 주요 업무 방법 을 실현 하 는 것 을 책임 지고 업무 대리 류 는 호출 된 업무 방법 에 대해 차단,여과,예비 처 리 를 책임 진다.주로 방법 에서 먼저 예비 처리 동작 을 한 다음 에 업무 실현 류 를 호출 하 는 방법 도 규정 하고 호출 후의 조작 도 규정 할 수 있다.우리 가 업 무 를 호출 해 야 할 때 업무 실현 류 를 통 해 직접 호출 하 는 것 이 아니 라 업무 대리 류 의 동명 방법 을 통 해 대리 류 가 처리 한 업무 방법 을 호출 하 는 것 이다.정적 에이전트 의 실현:1:먼저 인 터 페 이 스 를 정의 하고 업무 논 리 를 설명 합 니 다.
 package net.battier.dao;      
    /** 
     *          
     * @author Administrator
     */  
    public interface Count {  
        //     
        public void queryCount();  
      
        //       
        public void updateCount();  
      
    } 

2:그 다음 에 업무 실현 유형 을 정의 하고 업무 논리 인 터 페 이 스 를 실현 한다.
import net.battier.dao.Count;    
/** 
 *    (      ) 
 *  
 * @author Administrator 
 *  
 */  
public class CountImpl implements Count {  
  
    @Override  
    public void queryCount() {  
        System.out.println("    ...");  
  
    }  
  
    @Override  
    public void updateCount() {  
        System.out.println("    ...");  
  
    }  
  
}  

3:업무 대리 류 정의:조합 을 통 해 대리 류 에서 업무 실현 대상 을 만들어 구체 적 인 업무 방법 을 호출 합 니 다.업무 논리 인 터 페 이 스 를 실현 함으로써 업무 방법 을 통일 한다.프 록 시 클래스 에서 업무 논리 인터페이스 에서 의 방법 을 실현 할 때 예비 처리 작업 을 하고 업 무 를 통 해 클래스 대상 이 진정한 업무 방법 을 호출 하 며 호출 후 조작 하 는 정 의 를 실현 합 니 다.
public class CountProxy implements Count {  
    private CountImpl countImpl;  //                        
  
    /** 
     *         
     *  
     * @param countImpl 
     */  
    public CountProxy(CountImpl countImpl) {  
        this.countImpl = countImpl;  
    }  
  
    @Override  
    public void queryCount() {  
        System.out.println("        ——————");  
        //            
        countImpl.queryCount();  
        System.out.println("      ————————");  
    }  
  
    @Override  
    public void updateCount() {  
        System.out.println("          ——————");  
        //            
        countImpl.updateCount();  
        System.out.println("      ——————————");  
  
    }  
  
}  

4:사용 할 때 먼저 업무 실현 대상 을 만 든 다음 에 업무 실현 대상 을 구조 적 매개 변수 로 대리 대상 을 만 들 고 마지막 으로 대리 대상 을 통 해 업무 방법 을 호출 합 니 다.
 public static void main(String[] args) {  
        CountImpl countImpl = new CountImpl();  
        CountProxy countProxy = new CountProxy(countImpl);  
        countProxy.updateCount();  
        countProxy.queryCount();  
  
    }  

정적 에이전트 의 단점 은 매우 뚜렷 하 다.하나의 에이전트 클래스 는 하나의 업무 인터페이스의 실현 클래스 만 포장 할 수 있 고 여러 개의 업무 인터페이스 가 있 으 면 많은 실현 클래스 와 에이전트 클래스 를 정의 해 야 한다.그리고 만약 에 프 록 시 클래스 가 업무 방법 에 대한 사전 처리,호출 후 작업 이 모두 같다 면(예 를 들 어 호출 전 출력 알림,호출 후 자동 으로 연결 을 닫 는 것)여러 개의 프 록 시 클래스 에 중복 코드 가 많 을 것 이다.이때 우 리 는 이러한 대리 류 를 정의 할 수 있 습 니 다.모든 실현 류 의 방법 을 대리 할 수 있 습 니 다.들 어 오 는 업무 실현 류 와 방법 명 에 따라 구체 적 으로 호출 할 수 있 습 니 다.바로 동적 대리 입 니 다.
 
2.동적 에이전트 의 첫 번 째 실현-JDK 동적 에이전트
JDK 동적 에이전트 에 사용 되 는 프 록 시 클래스 는 프로그램 이 프 록 시 클래스 대상 으로 호출 될 때 만 JVM 이 진정 으로 만 듭 니 다.JVM 은 들 어 오 는 업무 실현 클래스 대상 과 방법 명 에 따라 프 록 시 클래스 의 class 파일 을 동적 으로 만 들 고 바이트 코드 엔진 에 의 해 실 행 된 다음 에 이 프 록 시 클래스 대상 을 통 해 호출 됩 니 다.우리 가 해 야 할 일 은 대리 류 의 예비 처리,호출 후 조작 만 지정 하면 된다.1:우선,업무 논리 인터페이스 정의
  public interface BookFacade {  
        public void addBook();  
    } 

2:그리고 업무 논리 인터페이스 구축 업무 실현 클래스 실현
public class BookFacadeImpl implements BookFacade {   
    @Override  
    public void addBook() {  
        System.out.println("      。。。");  
    }  
  
} 

3:마지막 으로 호출 관리 인터페이스 InvocationHandler 를 실현 하여 동적 에이전트 클래스 를 만 듭 니 다.
public class BookFacadeProxy implements InvocationHandler {  
    private Object target;//          ,            
    /** 
     *                 
     */  
    public Object bind(Object target) {  
        this.target = target;  //           

       //      ,              。           
       //       ,             (             ,               )、  、handler   
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),  
                target.getClass().getInterfaces(), this); }  
    /** 
     *       :     、      
     */  
    public Object invoke(Object proxy, Method method, Object[] args)  
            throws Throwable {  
        Object result=null;  

        System.out.println("     ——————");  
        //           
        result=method.invoke(target, args);  

        System.out.println("     ——————");  
        return result;  
    }  
  
}  

4:사용 할 때 먼저 업무 실현 대상 과 프 록 시 대상 을 만 든 다음 인터페이스 참조(여기 서 위로 전환)를 정의 하고 프 록 시 대상.bid(업무 실현 대상)의 반환 값 으로 값 을 부여 합 니 다.마지막 으로 인 터 페 이 스 를 통 해 호출 업무 방법 을 인용 하면 됩 니 다.(인터페이스 참조 가 진정 으로 가리 키 는 것 은 업무 류 에 연 결 된 프 록 시 대상 이기 때문에 인터페이스 방법 명 을 통 해 프 록 시 되 는 방법 들 을 호출 합 니 다)
  public static void main(String[] args) {  
            BookFacadeImpl bookFacadeImpl=new BookFacadeImpl();
            BookFacadeProxy proxy = new BookFacadeProxy();  
            BookFacade bookfacade = (BookFacade) proxy.bind(bookFacadeImpl);  
            bookfacade.addBook();  
        } 

JDK 동적 에이전트 의 프 록 시 대상 이 생 성 될 때 업무 실현 클래스 가 구현 하 는 인 터 페 이 스 를 매개 변수 로 사용 해 야 합 니 다(뒤에 프 록 시 방법 이 있 을 때 인터페이스 내 방법 명 에 따라 호출 해 야 하기 때 문 입 니 다).업무 수행 클래스 가 인 터 페 이 스 를 실현 하지 않 고 업무 방법 을 직접 정의 한다 면 JDK 동적 대 리 를 사용 할 수 없습니다.또한 업무 실현 류 에 인터페이스 에 없 는 방법 이 추가 되면 이 방법 들 은 대리 할 수 없습니다(호출 될 수 없 기 때 문 입 니 다).
3.동적 에이전트 의 두 번 째 실현-CGlib
cglib 는 클래스 를 대상 으로 대 리 를 실현 하 는 것 으로 원 리 는 지 정 된 업무 클래스 에 대해 하위 클래스 를 생 성하 고 그 중의 업무 방법 을 덮어 대 리 를 실현 하 는 것 이다.계승 을 채택 하기 때문에 final 수식 류 를 대리 할 수 없습니다.1:우선 업무 류 를 정의 하고 인 터 페 이 스 를 실현 할 필요 가 없다(물론 인 터 페 이 스 를 실현 해도 되 고 영향 을 주지 않 는 다)
 public class BookFacadeImpl1 {  
        public void addBook() {  
            System.out.println("    ...");  
        }  
    }

2:MethodInterceptor 방법 프 록 시 인터페이스 구현,프 록 시 클래스 생 성
public class BookFacadeCglib implements MethodInterceptor {  
    private Object target;//     ,                 
  
    //   JDK        
    public Object getInstance(Object target) {  
        this.target = target;  //       
        Enhancer enhancer = new Enhancer(); //     ,         
        enhancer.setSuperclass(this.target.getClass());  //             ( :             )
        //    :             ,    CallBack, Callback     intercept()     
        enhancer.setCallback(this); 
       //               
       return enhancer.create(); 
    }
    //        
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { 
        System.out.println("   ——————");
        proxy.invokeSuper(obj, args); //     (   )   
        System.out.println("     ——————");
        return null; 
    } 
}

3:비 즈 니스 클래스 와 프 록 시 클래스 대상 을 만 든 다음 프 록 시 클래스 대상.getInstance(비 즈 니스 클래스 대상)를 통 해 동적 프 록 시 클래스 대상 을 되 돌려 줍 니 다(비 즈 니스 클래스 의 하위 클래스 입 니 다.비 즈 니스 클래스 참조 로 가리 킬 수 있 습 니 다).마지막 으로 동적 에이전트 대상 을 통 해 방법 을 호출 합 니 다.
 public static void main(String[] args) {      
            BookFacadeImpl1 bookFacade=new BookFacadeImpl1();
            BookFacadeCglib  cglib=new BookFacadeCglib();  
            BookFacadeImpl1 bookCglib=(BookFacadeImpl1)cglib.getInstance(bookFacade);  
            bookCglib.addBook();  
        }  

4.비교적 정적 대 리 는 코드 에서 하나의 업무 실현 유형 을 명시 적 으로 정의 하고 대리 류 에서 같은 이름 의 업무 방법 을 포장 하 며 사용 자 는 대리 류 를 통 해 포 장 된 업무 방법 을 호출 합 니 다.JDK 동적 대 리 는 인터페이스 에 있 는 방법 명 을 통 해 동적 으로 생 성 된 대리 류 에서 업무 실현 류 를 호출 하 는 동명 방법 입 니 다.CGlib 동적 에이 전 트 는 계승 업무 클래스 를 통 해 생 성 되 는 동적 에이 전 트 는 업무 클래스 의 하위 클래스 로 업무 재 작성 방법 을 통 해 에이 전 트 됩 니 다.

좋은 웹페이지 즐겨찾기