코드 를 통 해 자바 의 세 가지 프 록 시 모드 를 빠르게 이해 합 니 다.

에이전트 모드
프 록 시(Proxy)는 대상 에 대한 별도의 접근 방식,즉 프 록 시 대상 을 통 해 대상 에 접근 하 는 디자인 모델 이다.이렇게 하 는 장점 은 목표 대상 이 실현 되 는 토대 에서 추가 적 인 기능 조작,즉 목표 대상 의 기능 을 확장 할 수 있다 는 것 이다.
여기 서 프로 그래 밍 에 사용 되 는 사상:다른 사람 이 이미 쓴 코드 나 방법 을 마음대로 수정 하지 마 세 요.수정 이 필요 하 다 면 대리 방식 으로 이 방법 을 확장 할 수 있 습 니 다.
UML 그림 은 다음 과 같다.

에이전트 모드
정적 에이전트
정적 프 록 시 를 사용 할 때 인터페이스 나 부모 클래스 를 정의 해 야 합 니 다.피 대리 대상 은 대리 대상 과 함께 같은 인 터 페 이 스 를 실현 하거나 같은 부 류 를 계승 한다.
코드 예제:

interface Source{ void method();}
class OldClass implements Source{
@Override
public void method() {
}
}
class Proxy implements Source{
private Source source = new OldClass();
void doSomething(){}
@Override
public void method() {
new Class1().Func1();
source.method();
new Class2().Func2();
doSomething();
}
public static void main(String[] args) {
Proxy proxy = new Proxy();
proxy.method();
}
}
정적 에이전트 부족:
대리 대상 은 목표 대상 과 같은 인터페이스 나 부모 클래스 를 실현 해 야 하기 때문에 대리 클래스 가 너무 많 습 니 다.또한 인터페이스 가 증가 하면 대상 과 대리 대상 을 모두 유지 해 야 한다.
동적 에이전트
JDK 에서 동적 프 록 시 클래스 는 java.lang.reflect.Proxy.newProxyInstance 방법 만 사용 하면 됩 니 다.이 방법 은 세 개의 인 자 를 받 아야 합 니 다.완전한 쓰기 방법 은:static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h ) 이 방법 은 Proxy 클래스 에서 정적 방법 이 고 받 은 세 개의 매개 변 수 는 다음 과 같 습 니 다.
  • ClassLoader loader:현재 대상 을 지정 하여 클래스 로 더 를 사용 합 니 다.로 더 를 얻 는 방법 은 고정 적 인 것 입 니 다
  • Class[] interfaces:목표 대상 이 실현 하 는 인터페이스 유형 은 일반적인 방식 으로 유형 을 확인 하고 인터페이스 유형 을 얻 는 방법 은 고정 적 인 것 입 니 다
  • InvocationHandler h;이벤트 처리,대상 의 방법 을 실행 할 때 이벤트 프로세서 의 방법 을 촉발 하고 현재 실행 대상 의 방법 을 매개 변수 로 전달한다
  • 코드 예제:
    
    /**
    *   
    */
    interface IUserDao {
    void save();
    }
    /**
    *     
    *     
    */
    class UserDao implements IUserDao {
    public void save() {
    System.out.println("----      !----");
    }
    }
    /**
    *         
    *            ,          
    */
    class ProxyFactory {
    //        
    private Object target;
    public ProxyFactory(Object target) {
    this.target = target;
    }
    //           
    public Object getProxyInstance() {
    return Proxy.newProxyInstance(
    target.getClass().getClassLoader(),
    target.getClass().getInterfaces(),
    (proxy, method, args) -> {
    System.out.println("    ");
    //        
    Object returnValue = method.invoke(target, args);
    System.out.println("    ");
    return returnValue;
    });
    }
    }
    /**
    *    
    */
    class App {
    public static void main(String[] args) {
    //     
    IUserDao target = new UserDao();
    // System.out.println(target.getClass());
    //      ,      
    IUserDao proxy = (IUserDao) new ProxyFactory(target).getProxyInstance();
    // System.out.println(proxy.getClass());
    //         
    proxy.save();
    }
    }
    메모:대리 대상 은 인 터 페 이 스 를 실현 할 필요 가 없 지만 목표 대상 은 반드시 인 터 페 이 스 를 실현 해 야 합 니 다.그렇지 않 으 면 동적 대 리 를 사용 할 수 없습니다.
    cglib 에이전트
    정적 에이전트 와 동적 에이전트 모델 은 모두 목표 대상 에 게 인 터 페 이 스 를 실현 하도록 요구 하지만 가끔 은 목표 대상 이 하나의 단독 대상 일 뿐 어떠한 인터페이스 도 실현 하지 못 한다.이 럴 때 목표 대상 서브 클래스 의 방식 으로 대 리 를 실현 할 수 있다.이런 방법 을 Cglib 대리 라 고 부른다.
    Cglib 대 리 는 하위 클래스 에이전트 라 고도 부 릅 니 다.메모리 에 하위 클래스 대상 을 구축 하여 대상 기능 에 대한 확장 을 실현 합 니 다.Cglib 는 강력 한 고성능 코드 생 성 패키지 로 실행 기간 에 자바 류 를 확장 하고 자바 인 터 페 이 스 를 실현 할 수 있 습 니 다.그것 은 많은 AOP 의 프레임 워 크 에 의 해 광범 위 하 게 사용 되 고 방법 을 제공 하 는 interception(차단),예 를 들 어 모두 가 알 고 있 는 Spring AOP 등 이다.
    cglib 패키지 의 밑바닥 은 작고 빠 른 바이트 처리 프레임 ASM 을 사용 하여 바이트 코드 를 변환 하고 새로운 클래스 를 생 성 합 니 다.cglib 하위 에이전트 가 주의해 야 할 것 은:
    1.Cglib 의 jar 파일 을 도입 해 야 하지만 Spring 의 핵심 패키지 에는 Cglib 기능 이 포함 되 어 있 기 때문에 spring-core-xxx.jar 를 직접 도입 하면 됩 니 다.(스프링 3.2 이후 에 야 Cglib 포함)
    2.대리 클래스 는 final 일 수 없습니다.그렇지 않 으 면 잘못 보고 합 니 다.
    3.목표 대상 의 방법 이 final/static 이면 차단 되 지 않 습 니 다.즉,목표 대상 의 추가 업무 방법 을 수행 하지 않 습 니 다.
    코드 예제:
    
    public class test {
    public static void main(String[] args) {
    //    
    UserDao target = new UserDao();
    //    
    UserDao proxy = (UserDao) new ProxyFactory(target).getProxyInstance();
    //         
    proxy.save();
    }
    }
    /**
    *     ,        
    */
    class UserDao {
    public void save() {
    System.out.println("----      !----");
    }
    }
    /**
    * Cglib      
    *  UserDao              
    */
    class ProxyFactory implements MethodInterceptor {
    //       
    private Object target;
    public ProxyFactory(Object target) {
    this.target = target;
    }
    //              
    public Object getProxyInstance() {
    //1.   
    Enhancer en = new Enhancer();
    //2.    
    en.setSuperclass(target.getClass());
    //3.      
    en.setCallback(this);
    //4.    (    )
    return en.create();
    }
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
    System.out.println("    ...");
    //          
    Object returnValue = method.invoke(target, args);
    System.out.println("    ...");
    return returnValue;
    }
    }
    이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

    좋은 웹페이지 즐겨찾기