jdk 와 cglib 에이전트 차이
7889 단어 op 에이전트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 동적 에이 전 트 는 계승 업무 클래스 를 통 해 생 성 되 는 동적 에이 전 트 는 업무 클래스 의 하위 클래스 로 업무 재 작성 방법 을 통 해 에이 전 트 됩 니 다.