자바 동적 에이전트 방법 및 결함

11619 단어 Java자바proxyaop
본문 부분 은 오리지널 로 대부분 다크호스 프로그래머 과정의 추출 이다.
1 동적 에이전트 소개
특징: 바이트 코드 는 사용 에 따라 만 들 고 불 러 오 는 역할 을 수행 합 니 다. 원본 코드 를 수정 하지 않 는 토대 에서 방법 을 강화 합 니 다. 이 과정 에서 새로운 대상 을 만 들 것 입 니 다.분류: 인터페이스 기반 동적 에이전트, 하위 클래스 기반 동적 에이전트
2 인터페이스 기반 동적 에이전트:
      :Proxy
     :JDK  

프 록 시 대상 을 만 드 는 요구: 프 록 시 클래스 에 의 해 최소한 하나의 인 터 페 이 스 를 실현 하고 없 으 면 사용 할 수 없 으 며, 새 대상 은 인터페이스 여야 합 니 다.프 록 시 대상 을 만 드 는 방법: Object Proxy. new Proxy Instance (ClassLoader, Class [], InvocationHandler) 방법의 인자: ClassLoader: 클래스 로 더 는 프 록 시 대상 바이트 코드 를 불 러 오 는 데 사 용 됩 니 다.프 록 시 대상 과 같은 종류의 로 더 를 사용 합 니 다.고정 표기 법.Class []: 바이트 코드 배열 은 프 록 시 대상 과 피 프 록 시 대상 이 같은 방법 을 가지 도록 하 는 데 사 용 됩 니 다.고정 표기 법.Invocation Handler: 증강 코드 를 제공 하 는 데 사용 되 는 것 은 우리 가 어떻게 대리 하 는 지 쓰 라 는 것 입 니 다.우 리 는 일반적으로 이 인터페이스의 실현 류 이 며, 일반적으로 익명 내부 류 이지 만, 필요 한 것 은 아니다.이 인터페이스의 실현 류 는 모두 누가 쓰 고 누가 쓰 는 것 입 니까?
예 를 들 어 Producer 는 피 에이전트 대상 이 고 IProducer 는 인터페이스 IProducer proxy Producer = (IProducer) Proxy. newProxyInstance (producer. getClass (). getClassLoader (), producer. getClass (). getInterfaces (), new Invocation Handler (){/ * * 역할: 피 에이전트 대상 의 모든 인터페이스 방법 을 실행 할 때 이 방법 * 방법 매개 변수의 의미 * @ param proxy 에이전트 대상 의 인용 을 거 칩 니 다. method. invoke (proxy) 를 사용 하지 마 십시오. 그러면 프로그램 이 순환 에 빠 집 니 다. invoke ()방법 이 들 어 오 는 대상 은 외부 에서 * @ param method 가 현재 실행 하 는 방법 * @ param args 현재 실행 방법 에 필요 한 매개 변수 * @ return 과 피 프 록 시 대상 방법 이 같은 반환 값 * @ throws Throwable * / @ Override public Object invoke (Object proxy, Method method, Object [] args) throws Throwable{/ / 강 화 된 코드 를 제공 합 니 다 Object returnValue = null;
            //1.         
            Float money = (Float)args[0];
            //2.           
            if("saleProduct".equals(method.getName())) {
                returnValue = method.invoke(producer, money0.8f);
            }
            return returnValue;
        }
    });

proxyProducer.saleProduct(10000f);
3 하위 클래스 기반 동적 에이전트
제3자 패키지 에서 cglib cglib 2.1 3 과 관련 된 클래스 를 제공 합 니 다. Enhancer 공급 자: 제3자 cglib 라 이브 러 리 에서 프 록 시 대상 을 만 드 는 요구: 피 프 록 시 클래스 는 최종 클래스 에서 프 록 시 대상 을 만 드 는 방법 이 될 수 없습니다. Object Enhancer. create (Class, Callback) 방법의 매개 변수: Class: 바이트 코드 는 피 프 록 시 대상 을 지정 하 는 바이트 코드 입 니 다.
  Callback:         。          。                ,            ,      。             。
                        :MethodInterceptor

Producer cglibProducer = (Producer) Enhancer. create (producer. getClass (), new MethodInterceptor () {/ * * * 역할: 피 에이전트 대상 의 모든 인터페이스 방법 을 실행 할 때 이 방법 * @ param proxy 에이전트 대상 의 인용 을 거 칩 니 다. method. invoke (proxy) 를 사용 하지 마 십시오.방법 이 들 어 오 는 대상 은 외부 에서 * @ param method 현재 실행 방법 * @ param args 현재 실행 방법 에 필요 한 매개 변수 * 이상 세 개의 매개 변수 와 인터페이스 기반 동적 에이전트 에서 invoke 방법의 매개 변 수 는 같 습 니 다 * @ param methodProxy: 현재 실행 방법의 대리 대상 * @ return * @ throws Throwable * / @ Override public Object intercept(Object proxy, Method method, Object [] args, MethodProxy methodProxy) throws Throwable {/ / 증강 코드 제공 Object returnValue = null;
    //1.         
    Float money = (Float)args[0];
    //2.           
    if("saleProduct".equals(method.getName())) {
        returnValue = method.invoke(producer, money*0.8f);
    }
    return returnValue;
}

}); cglibProducer.saleProduct(12000f);
결함
동적 에이전트 에 큰 결함 이 있 습 니 다. 이것 은 하위 클래스 와 인 터 페 이 스 를 기반 으로 하 는 동적 에이전트 방법 에 모두 존재 합 니 다. 다음은 인 터 페 이 스 를 기반 으로 하 는 동적 에이전트 방법 으로 예 를 들 어 1) 인 터 페 이 스 를 만 듭 니 다.
public interface Fruit {
    public void eat();
    public void run();
}

2) 대 리 될 클래스 만 들 기
public class Apple implements Fruit {
    @Override
    public void eat() {
        System.out.println("       ");
    }
    public void run(){
        System.out.println("      !!!");
        eat();
    }
}

3) 사 과 를 먹 기 전에 손 을 씻 고 싶 습 니 다. 달리기 전에 몸 을 풀 고 싶 습 니 다.
public class Demo1 {
    @Test
    public void demo1(){
        final Apple apple = new Apple();
        final Fruit apple1 = (Fruit)Proxy.newProxyInstance(apple.getClass().getClassLoader(), apple.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                if("run".equals(method.getName()))
                    System.out.println("      ");
                if("eat".equals(method.getName()))
                    System.out.println("    ");
                method.invoke(apple);
                return null;
            }
        });
        System.out.println("apple1   :");
        apple1.run();
    }
}

실행 결과
apple1   :
      
      !!!
       

발견: 나 는 사 과 를 먹 기 전에 손 을 씻 지 않 았 다!증강했어

좋은 웹페이지 즐겨찾기