자바 와 모드 - 동적 에이전트 모드

22591 단어 자바
에이전트 모드
프 록 시 모드: 다른 대상 에 게 대역 이나 자리 표시 자 를 제공 하여 이 대상 에 대한 접근 을 제어 합 니 다.프 록 시 모드 를 사용 하여 프 록 시 대상 을 만 들 고 프 록 시 대상 이 특정한 대상 의 접근 을 제어 하도록 합 니 다. 프 록 시 대상 은 원 격 대상 이나 안전 통제 가 필요 한 대상 일 수 있 습 니 다.나 는 C 언어 에서 포인터 가 하나의 대리 대상 이 고 데 이 터 를 진정 으로 저장 하 는 것 은 메모리 의 다른 구역 이 라 고 생각한다.자바 는 API 를 제공 하여 동적 프 록 시 를 생 성 할 수 있 기 때문에 표준 프 록 시 모드 를 정적 프 록 시 모드 라 고 부른다.정적 에이전트 모델 에서 세 가지 역할 이 있 는데 이 세 가지 역할 을 이해 하면 에이전트 모델 을 이해 할 수 있다.
a. 추상 적 인 대상: 실제 캐릭터 와 추상 적 인 캐릭터 의 공공 인터페이스 (클래스 일 수도 있 고 인터페이스 일 수도 있다) Subject 를 정의 했다.
b. 대리 역할: 대리 역할 내부 에 실제 캐릭터 에 대한 인용 이 포함 되 어 있 고 이 인용 을 통 해 실제 캐릭터 가 완성 하고 자 하 는 임 무 를 수행 합 니 다.그 밖 에 대리 역할 은 다른 기능 을 완성 할 수 있다.
c. 실제 역할: 실제 임 무 를 완성 해 야 하 는 역할 은 우리 가 시종 인용 해 야 할 대상 이다.
대리 역할 과 실제 역할 은 모두 추상 적 인 역할 을 실현 했다.
코드 를 써 서 예 를 들 면:
//    ,      
interface Subject { 
    public void request();
}

//    
class RealSubject implements Subject {
    public void request() {
        do something;
   } 
}

//    ,           
class ProxySubject implements Subject {
    private RealSubject sub;
    
    public ProxySubject(RealSubject obj) {
        this.sub = obj;//           
    }

   public void request() {
       sub.request();//                    
  }
}

public static void main(String[] args) {
		Subject proxy = new ProxySubject();
		proxy.request();
}

프 록 시 모델 은 여러 가지 변형 이 있 습 니 다. 이것 은 연구 할 만 한 가치 가 있 지만 오늘 제 중점 은 자바 의 동적 대리 입 니 다.
동적 에이전트
위의 프 록 시 모드 에 문제 가 있 습 니 다. 그것 은 서로 다른 인터페이스 에 프 록 시 클래스 를 따로 제공 해 야 한 다 는 것 입 니 다.현재 이런 문제 가 있 습 니 다. 시스템 에 10 가지 방법 이 호출 되 기 전에 안전 검증 을 해 야 합 니 다. 이 10 가지 유형 은 각각 다른 인 터 페 이 스 를 실현 합 니 다.이런 상황 은 바로 대리 모델 이 역할 을 발휘 하 는 곳 이다. 진정한 방법 이 호출 되 기 전에 현재 대리 류 에서 안전 검증 을 하고 통과 되면 진정한 방법 을 호출 하고 그렇지 않 으 면 돌아간다.이렇게 하면 안전 검증 의 목적 을 달성 할 뿐만 아니 라 개폐 원칙 도 위반 하지 않 는 다.그러나 안전 검증 은 모두 똑 같 습 니 다. 우 리 는 정말 10 개의 대리 류 를 실현 한 다음 에 똑 같은 안전 검증 을 해 야 합 니까?코드 를 반복 하 는 것 은 나 쁜 기운 을 의미 하 는 거 야.자바 의 동적 대 리 는 우리 가 이 일 을 해결 하 는 데 도움 을 줄 수 있다.동적 대 리 는 말 그대로 동적 으로 대리 류 를 생 성하 고 대리 서 비 스 를 하 는 것 이다.자바 의 동적 대 리 를 보기 전에 동적 대 리 를 실현 하려 면 어떤 조건 이 필요 한 지 분석 해 보 세 요.
(1) 프 록 시 모드 에서 클 라 이언 트 는 실제 적 으로 프 록 시 역할 과 접촉 하고 있다. 이 는 실제 대상 이 라 고 생각 하지만 사실은 프 록 시 대상 이다. 그러나 이런 프 록 시 는 클 라 이언 트 에 대해 투명 하 다. 클 라 이언 트 는 인 터 페 이 스 를 대상 으로 프로 그래 밍 을 하 는데 추상 적 인 인터페이스 만 있 고 구체 적 인 실현 유형 을 모른다.그래서 우 리 는 추상 적 인 인 터 페 이 스 를 정의 해 야 한다. 실제 역할 과 대리 역할 은 모두 추상 적 인 인 터 페 이 스 를 실현 하면 클 라 이언 트 에 대한 투명 한 대 리 를 실현 할 수 있다.
(2) 동적 대리 도 대리 일 뿐이다. 대 리 는 진정한 방법 이 집행 되 기 전이 나 그 후에 논 리 를 추가 하 는 것 이 아니 라 주요 한 업무 논 리 는 실제 역할 이 실현 되 어야 하기 때문에 반드시 실제 역할 이 있어 야 한다.이것 은 정적 에이전트 모드 와 같 습 니 다.우 리 는 여전히 업무 논리 에 따라 RealSubject 를 정의 해 야 한다.
(3) 동적 에이전트 역시 에이전트 류 가 필요 합 니 다. 정적 에이전트 와 의 차 이 는 정적 에이전트 류 는 프로그래머 에 의 해 생 성 되 고 동적 에이전트 류 는 동적 으로 생 성 됩 니 다.그러나 동적 대리 류 의 성질 은 일반적인 대리 류 와 같다. 모두 a. 추상 적 인 역할 인 터 페 이 스 를 실현 해 야 한다. 이것 은 동적 으로 생 성 된 것 이기 때문에 어떤 인 터 페 이 스 를 실현 해 야 할 지 모 르 기 때문에 실제 역할 이 실현 하 는 모든 인 터 페 이 스 를 실현 해 야 한다.b. 캐릭터 의 인용 저장 하기;
앞의 두 가지 조건 은 정적 에이전트 모델 과 같 습 니 다. 우 리 는 관심 을 가 질 필요 가 없습니다. 우리 가 알 아야 할 문 제 는 동적 에이전트 류 에 필요 한 인터페이스 와 그것 이 어떻게 대리 방법 으로 호출 되 는 지 하 는 것 입 니 다.
동적 프 록 시 클래스 생 성
동적 프 록 시 를 실현 하기 위해 자바 는 프 록 시 클래스 와 InvocationHandler 인 터 페 이 스 를 제공 합 니 다. 프 록 시 클래스 는 동적 프 록 시 클래스 를 생 성 하 는 데 사 용 됩 니 다. InvocationHandler 인 터 페 이 스 는 프 록 시 클래스 가 실제로 발생 하 는 곳 입 니 다. 퍼 블 릭 Object invoke (Object proxy, Method method, Object [] args) throws Throwable, 프 록 시 클래스 의 모든 방법 호출 은 invoke () 방법 으로 전 환 됩 니 다.다음 에 우 리 는 이 방법 을 말 하고 있 습 니 다. 먼저 프 록 시 류 가 동적 프 록 시 류 를 어떻게 생 성 하 는 지 보 겠 습 니 다.Proxy 는 다음 과 같은 방법 을 제공 합 니 다.
//       proxy   InvocationHandler
static InvocationHandler getInvocationHandler(Object proxy) 
//   loader  ,   interfaces      
static Class<?>	getProxyClass(ClassLoader loader, Class<?>... interfaces)
//  cl      
static boolean	isProxyClass(Class<?> cl) 
//   loader  ,   interfaces         ,    InvocationHandler h
static Object	newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
프 록 시가 제공 한 네 가지 방법 은 모두 static 이 고 사실은 프 록 시 팩 토리 라 고 해 야 한 다 는 것 을 알 수 있다.상기 방법 에 대한 구체 적 인 내용 은 자바 독 을 볼 수 있 지만 동적 에이전트 의 실현 을 잘 보기 위해 프 록 시의 소스 코드 를 연구 하기 로 했 습 니 다.편폭 을 고려 할 때 일부 소스 코드 만 선택 했다.
 class Proxy implements java.io.Serializable {
	
	/*            :$Proxy      ,      nextUniqueNumber++*/
	private static long nextUniqueNumber = 0;
    private final static String proxyClassNamePrefix = "$Proxy";

    /**             */
    private final static Class[] constructorParams = { InvocationHandler.class };

    /*    ClassLoader       */
    private static Map<ClassLoader, Map<List<String>, Object>> loaderToCache
        = new WeakHashMap<>();

    /**              */
    private static Object pendingGenerationMarker = new Object();

    /** next number to use for generation of unique proxy class names */
    private static Object nextUniqueNumberLock = new Object();

    /**       ,                      proxyClasses  */
    private static Map<Class<?>, Void> proxyClasses =
        Collections.synchronizedMap(new WeakHashMap<Class<?>, Void>());

    /*   InvocationHandler*/
    protected InvocationHandler h;

   /*           */
    protected Proxy(InvocationHandler h) {
        doNewInstanceCheck();
        this.h = h;
    }

   /*     ,      loader  ,   interfaces      ,     getProxyClass0()  */
    public static Class<?> getProxyClass(ClassLoader loader,
                                         Class<?>... interfaces)
        throws IllegalArgumentException
    {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            checkProxyAccess(Reflection.getCallerClass(), loader, interfaces);
        }

        return getProxyClass0(loader, interfaces);
    }


    /**
     *           :
     * 1.               65535,  Java         
     * 2.  interfaces(       ),         interfaceNames,  :
     *         interfaceNames    Class  ,        ,   
     *          Class      ,   
     *             ,   (interfaceSet             ,               )
     * 3.  loader loaderToCache                  map,    ,       Map   
     * 4.             List,  3   map   :
     *           loader       interfaces        ,         
     *          loader      interface      ,  ,       //point1
     *                  ,   5 
     *            while(true)   ,  point1         
     * 5.       ,  interfaces  non-public   ,          non-public     ,
     *     interfaces    non-public         ,           ;
     *         public  ,        com.sun.proxy  
     * 6.       :$Proxy   
     * 7.               ,           proxyClasses,  isProxy()    
     * 8.          3  map ,  point1      ,            
     * @param loader
     * @param interfaces
     * @return
     */
    private static Class<?> getProxyClass0(ClassLoader loader,Class<?>... interfaces) {
    	//             65535,  Java         
    	if (interfaces.length > 65535) {
            throw new IllegalArgumentException("interface limit exceeded");
        }
    	//        
        Class<?> proxyClass = null;

        /*                */
        String[] interfaceNames = new String[interfaces.length];

        //             
        Set<Class<?>> interfaceSet = new HashSet<>();

        //      ,       2 
        for (int i = 0; i < interfaces.length; i++) {
        	//                       
            String interfaceName = interfaces[i].getName();
            Class<?> interfaceClass = null;
            try {
                interfaceClass = Class.forName(interfaceName, false, loader);
            } catch (ClassNotFoundException e) {
            }
            if (interfaceClass != interfaces[i]) {
                throw new IllegalArgumentException(
                    interfaces[i] + " is not visible from class loader");
            }

           /*            */
            if (!interfaceClass.isInterface()) {
                throw new IllegalArgumentException(
                    interfaceClass.getName() + " is not an interface");
            }

            /*          */
            if (interfaceSet.contains(interfaceClass)) {
                throw new IllegalArgumentException(
                    "repeated interface: " + interfaceClass.getName());
            }
            interfaceSet.add(interfaceClass);

            interfaceNames[i] = interfaceName;
        }

        /*          List,     key map   ,              */
        List<String> key = Arrays.asList(interfaceNames);

        /*   loader            map*/
        Map<List<String>, Object> cache;
        synchronized (loaderToCache) {
            cache = loaderToCache.get(loader);
            if (cache == null) {
                cache = new HashMap<>();
                loaderToCache.put(loader, cache);
            }
        }

        synchronized (cache) {
        	/**
        	 *        while(true)   :
        	 * (1)                 ,       ,    
        	 * (2)                 ,  ,      ,    (1),     
        	 * (3)  ,         ,        ,     ,    (1)
        	 */
            do {
                Object value = cache.get(key);
                if (value instanceof Reference) {
                    proxyClass = (Class<?>) ((Reference) value).get();
                }
                if (proxyClass != null) {
                    return proxyClass;
                } else if (value == pendingGenerationMarker) {
                    try {
                        cache.wait();
                    } catch (InterruptedException e) {
                    }
                    continue;
                } else {
                    cache.put(key, pendingGenerationMarker);
                    break;
                }
            } while (true);
        }

        try {
        	//     
            String proxyPkg = null;    

            /*         non-public ,         non-public        ,    com.sun.proxy*/
            for (int i = 0; i < interfaces.length; i++) {
                int flags = interfaces[i].getModifiers();
                if (!Modifier.isPublic(flags)) {
                    String name = interfaces[i].getName();
                    int n = name.lastIndexOf('.');
                    String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
                    if (proxyPkg == null) {
                        proxyPkg = pkg;
                    } else if (!pkg.equals(proxyPkg)) {
                        throw new IllegalArgumentException(
                            "non-public interfaces from different packages");
                    }
                }
            }

            if (proxyPkg == null) {
                proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
            }

            {
               /*      ,  $Proxy     */
                long num;
                synchronized (nextUniqueNumberLock) {
                    num = nextUniqueNumber++;
                }
                String proxyName = proxyPkg + proxyClassNamePrefix + num;
                /*     */
                byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
                    proxyName, interfaces);
                try {
                    proxyClass = defineClass0(loader, proxyName,
                        proxyClassFile, 0, proxyClassFile.length);
                } catch (ClassFormatError e) {
                    throw new IllegalArgumentException(e.toString());
                }
            }
            //   proxyClasses ,isProxy()        
            proxyClasses.put(proxyClass, null);

        } finally {
           /*            */
            synchronized (cache) {
                if (proxyClass != null) {
                    cache.put(key, new WeakReference<Class<?>>(proxyClass));
                } else {
                    cache.remove(key);
                }
                cache.notifyAll();
            }
        }
        return proxyClass;
    }

    
    /**
     *         
     * 1.    getProxyClass0()      Class  
     * 2.             Constructor  
     * 3.  Constructor.newInstance()
     *    InvocationHandler  
     */
    public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
    {
        //   loader  ,    interfaces        
        Class<?> cl = getProxyClass0(loader, interfaces);
        final Constructor<?> cons = cl.getConstructor(constructorParams);
        final InvocationHandler ih = h;
        return newInstance(cons, ih);
    }

    //        ,    ,          
    private static Object newInstance(Constructor<?> cons, InvocationHandler h) {  
            return cons.newInstance(new Object[] {h} );
    }
    
    /*  cl      ,   proxyClasses   ,     */
    public static boolean isProxyClass(Class<?> cl) {
        if (cl == null) {
            throw new NullPointerException();
        }
        return proxyClasses.containsKey(cl);
    }
    
    /*   proxy   InvocationHandler,    proxy.h,    */
    public static InvocationHandler getInvocationHandler(Object proxy)
            throws IllegalArgumentException
        {
            final Proxy p = (Proxy) proxy;
            final InvocationHandler ih = p.h;
            return ih;
        }
}
프 록 시가 프 록 시 클래스 를 생 성 할 때 중요 한 작업 은 프 록 시 클래스 가 필요 한 인 터 페 이 스 를 실현 하도록 하 는 것 이다. 바이트 코드 를 생 성 하 는 작업 은 프 록 시 Generator 가 한다.동적 에이전트 클래스 를 생 성 할 때, 우 리 는 클래스 캐리어, 실현 해 야 할 인터페이스, 그리고 이와 관련 된 InvocationHandler 대상 에 게 전달 해 야 한다. InvocationHandler 대상 이 해 야 할 일 은 바로 우리 가 실현 하고 자 하 는 에이전트 논리 이다. 예 를 들 어, 우 리 는 모든 방법 을 사용 하기 전에 안전 검 사 를 하고 싶다. 그러면 InvocationHandler 의 invoke ()방법 에서 안전 검사 의 논 리 를 호출 합 니 다. invoke () 는 대리 가 발생 하 는 곳 입 니 다.invoke () 방법 을 살 펴 보 겠 습 니 다.
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
 其中proxy是代理类,不用去管它。method是要真实对象要执行的方法,也就是我们要代理的方法,args是method的参数,所以如果代理需要做安全检查的话,可以这么写:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    if(      )
        method.invoke(obj,args);
   else
       return null;
}

예 를 들 어 이렇게 많은 것 을 말 했 는데 우 리 는 동적 대 리 를 실현 하 는 예 입 니 다. 논 리 는 이 렇 습 니 다. 세 개의 모듈 이 있 는데 그것 이 바로 추가, 삭제, 수정 입 니 다. 이 코드 들 은 이미 완성 되 었 습 니 다.실제 작업 을 하기 전에 안전 검증 이 통과 되면 해당 하 는 방법 을 사용 해 야 한다. 그렇지 않 으 면 이번 작업 이 실패 할 것 이다.먼저 각 인터페이스 와 실현 을 정의 합 니 다.
//    
interface Add {
	public void add(String s);
}

class AddImp implements Add {
	public void add(String s) {
		System.out.println(s + "        ");
	}
}

//    
interface Delete {
	public void delete(String s);
}

class DeleteImp implements Delete {
	public void delete(String s) {
		System.out.println(s + "     ");
	}
}

//    
interface Update {
	public void update(String s);
}

class UpdateImp implements Update {
	public void update(String s) {
		System.out.println(s + "     ");
	}
}
안전 검사 모듈
/**
 *       ,              
 */
class SafeCheck {
	static Random rand = new Random(25);
	public static boolean check(Object obj) {
		if(rand.nextInt(20) > 10)
			return false;
		
		return true;
	}
}
동적 대 리 를 생 성하 고 대리 집행:
/**
 *            ,           
 *                         
 *             Proxy   ,               
 */
class DynamicProxy implements InvocationHandler {
	//    ,   Object
	private Object originalObj;
	
	/**
	 *              ,   originalObj   
	 */
	public Object bind(Object originalObj) {
		this.originalObj = originalObj;
		//originalObj   Class  
		Class<?> clazz = originalObj.getClass();
		//         ,   this      
		return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
	}
	/**
	 *        method    ,       null
	 *          ,           
	 *   ,proxy    ,method          ,   originalObj
	 */
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		//         ,         
		if(SafeCheck.check(originalObj))
			return method.invoke(originalObj, args);
		else 
			System.out.println(originalObj + "       !");
		//         
		return null;
	}
}
테스트 코드:
public class Client {

	public static void main(String[] args) {
		String name = "cxy";
		DynamicProxy handler = new DynamicProxy();
		//    
		Add add = new AddImp();
		Update update = new UpdateImp();
		Delete delete = new DeleteImp();
		
		//  Add    
		Add pa = (Add) handler.bind(add);
		//    
		pa.add(name);
		//  update    
		Update pu = (Update)handler.bind(update);
		pu.update(name);
		//  Delete    
		Delete pd = (Delete)handler.bind(delete);
		pd.delete(name);
	}
}
출력 결과:
----   com.understanding.loaderandengine.AddImp@f0a3e8     -----
cxy        
----   com.understanding.loaderandengine.UpdateImp@a22e0c     -----
com.understanding.loaderandengine.UpdateImp@a22e0c       !
----   com.understanding.loaderandengine.DeleteImp@1b56bda     -----
com.understanding.loaderandengine.DeleteImp@1b56bda       !

시스템 에 세 개의 모듈 이 있 고 서로 다른 인 터 페 이 스 를 실현 하지만 그들 이 대리 가 필요 한 논리 가 같다 면 하나의 처리 프로그램 만 제시 하면 모든 모듈 을 동적 으로 대리 할 수 있다 는 것 을 알 수 있다. 이것 은 동적 대리 의 강력 한 점 이다.이 예 는 이미 AOP 의 맛 이 난다. 안전 검 사 는 원래 모듈 에 침입 하 는 방식 을 바 꾸 지 않 고 모든 모듈 에 서 비 스 를 제공 했다. Spring 의 AOP 중 하 나 는 동적 대 리 를 통 해 이 루어 진 것 이다.
동적 에이전트 의 실행
앞에서 동적 에이전트 류 가 어떻게 생 성 되 는 지 소개 하고 동적 에이전트 의 예 도 보 여 주 었 습 니 다. 사실 우 리 는 동적 에이전트 류 가 어떻게 대리 서 비 스 를 하 는 지 보고 싶 습 니 다. 그러면 동적 에이전트 류 의 코드 를 봐 야 합 니 다. 아래 의 도구 류 를 통 해 동적 대리 류 를 생 성 할 수 있 습 니 다.
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Proxy;
import sun.misc.ProxyGenerator;

public class ProxyUtils {

	/*
	 *                         ,
	 *     clazz   
         * params :clazz            
         * proxyName :             
        */
	public static void generateClassFile(Class clazz,String proxyName)
	{
	  //              ,     
  byte[] classFile = ProxyGenerator.generateProxyClass(proxyName, clazz.getInterfaces()); 
		String paths = clazz.getResource(".").getPath();
		System.out.println(paths);
		FileOutputStream out = null;  
        
        try {
            //      
        	out = new FileOutputStream(paths+proxyName+".class");  
            out.write(classFile);  
            out.flush();  
        } catch (Exception e) {  
            e.printStackTrace();  
        } finally {  
            try {  
                out.close();  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        }  
	}
	
}
또는 main () 에 한 문장 을 추가 하여 프 록 시 클래스 를 생 성 합 니 다.
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
역 컴 파일 을 통 해 대리 류 의 소스 코드 를 얻 었 습 니 다. 소스 코드 가 있 으 면 모든 것 이 우리 앞 에 노출 됩 니 다. 먼저 AddImp 에 생 성 된 대리 류 를 보 세 요.
/**
 *      ,    Proxy ,     Add  
 */
public final class AddProxy extends Proxy
implements Add
{
private static Method m1;
private static Method m3;
private static Method m0;
private static Method m2;

//    InvocationHandler   ,           
public AddProxy(InvocationHandler paramInvocationHandler)
  throws 
{
  super(paramInvocationHandler);
}

/**
 *   Add      add  
 */
public final void add(String paramString)
  throws 
{
  try
  {
	//        InvocationHandler invoke()   
    this.h.invoke(this, m3, new Object[] { paramString });
    return;
  }
  catch (Error|RuntimeException localError)
  {
    throw localError;
  }
  catch (Throwable localThrowable)
  {
    throw new UndeclaredThrowableException(localThrowable);
  }
}


static
{
  try
  {
   //         add   Method  , InvocationHandler invoke()   ,        ,    m3          
    m3 = Class.forName("com.understanding.loaderandengine.Add").getMethod("add", new Class[] { Class.forName("java.lang.String") });
    m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
    m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
    m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
    return;
  }
  catch (NoSuchMethodException localNoSuchMethodException)
  {
    throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
  }
  catch (ClassNotFoundException localClassNotFoundException)
  {
    throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
  }
}
}
이상 의 코드 는 Object 계승 을 위해 생 성 된 hashCode (), toString (), equals () 방법 을 삭 제 했 습 니 다. 이 어 Delete 프 록 시 류 의 소스 코드 를 살 펴 보고 선택 하 십시오.
//   delete()        
public final void delete(String paramString)
    throws 
  {
    try
    {
      this.h.invoke(this, m3, new Object[] { paramString });
      return;
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

//      delte() Method  
m3 = Class.forName("com.understanding.loaderandengine.Delete").getMethod("delete", new Class[] { Class.forName("java.lang.String") });
Update 의 코드 는 붙 이지 않 습 니 다. 위의 코드 에서 우 리 는 동적 에이전트 의 실행 과정 을 발견 할 수 있 습 니 다.
(1) 동적 에이전트 클래스 는 InvocationHandler 의 인용 을 저장 해 야 합 니 다.
(2) 동적 에이전트 클래스 는 피 에이전트 클래스 가 실현 하 는 모든 인 터 페 이 스 를 실현 하고 해당 하 는 방법의 Method 대상 을 얻어 해당 하 는 방법 을 생 성 한다.
(3) 대 리 를 수행 할 때 동적 대리 류 는 사실 Invocation Handler. invoke () 방법 으로 넘 어 갔다. 이것 도 내 가 Invocation Handler 가 대리 역할 이 라 고 말 하 는 이유 이다.
여기 서 우 리 는 동적 대리 류 가 어떻게 생 성 되 고 동적 대리 가 어떻게 실현 되 는 지 알 게 되 었 고 작은 예 를 들 었 다. 이 작은 예 는 AOP 의 사상 이 있다.그런데 자바 에서 동적 에이 전 트 는 완벽 한 가요?프 록 시. getProxyclass) () 방법 을 돌 이 켜 보면 자바 의 동적 대 리 는 프 록 시 클래스 에 의 해 실 현 된 인터페이스 에 따라 대리 되 는 것 을 발견 할 수 있 습 니 다. 자바 의 동적 대 리 는 '인 터 페 이 스 를 위 한 대리' 라 고 할 수 있 습 니 다. 만약 에 하나의 클래스 가 인 터 페 이 스 를 실현 하지 않 으 면 동적 대리 류 를 생 성 할 수 없습니다. 이것 은 결함 이지 만 어 쩔 수 없 이 말 할 수 있 습 니 다.자바 의 동적 대 리 는 여전히 매우 강하 다.
전재 설명: 홍엽 을 비유 하 다.

좋은 웹페이지 즐겨찾기