참으로 흥미로운 문제입니다. 첫 번째 질문 : ExternalClass
이 일부 인터페이스를 구현합니까? 만약 그렇다면, 그것은하지 않는 경우 그러나, 당신은 하나를 만들 수 있습니다, 물건을 많이 단순화 :
interface ExternalClassFacade {
method1();
method2();
//...
method30();
}
걱정하지 마세요
, 당신이 그것을 구현할 필요가 없습니다! ExternalClass
에서 모든 메소드 서명을 복사하면됩니다. java.lang.Proxy
을 알고 계십니까? 당신처럼 이러한 문제에 멋진 도구 :이 마법과 모호한 코드 ExternalClassFacade
를 구현하고 ExternalClass
과 같은 방법을 실행할 수 있도록 만든 것을 볼 수 있듯이
ExternalClass ext = //obtain target ExternalClass somehow
ExternalClassFacade extFacade = (ExternalClassFacade) Proxy.newProxyInstance(
ExternalClass.class.getClassLoader(),
new Class<?>[]{ExternalClassFacade.class},
new BatchInvocationHandler(ext));
extFacade.method1();
. - 당신이 같은 인수 ExternalClass
에 같은 이름의 메서드 호출을 전달합니다 ExternalClassFacade
에 메서드를 호출 할 때이 코드 자체는 유용한 아무것도하지 않는
public class BatchInvocationHandler implements InvocationHandler {
private final ExternalClass ext;
public BatchInvocationHandler(ExternalClass ext) {
this.ext = ext;
}
@Override
public Object invoke(Object proxy, final Method method, final Object[] args) throws Throwable {
return MethodUtils.invokeMethod(ext, method.getName(), args);
}
}
: 여기에 누락 된 퍼즐입니다. 그래서 우리는 아직 아무것도 얻지 못했습니다. BTW 나는 반향 코드를 단순화하기 위해 Apache Commons Lang의 MethodUtils
을 사용하고 있습니다. CLASSPATH에 이미이 라이브러리가있을 가능성이 있습니다. 그렇지 않은 경우 추가 코드가 몇 줄 밖에 없습니다.
지금이 개선 된 버전을보고 :
private static class BatchInvocationHandler implements InvocationHandler {
private final ExternalClass ext;
private Queue<Callable<Object>> delayedInvocations = new ConcurrentLinkedQueue<Callable<Object>>();
public BatchInvocationHandler(ExternalClass ext) {
this.ext = ext;
}
@Override
public Object invoke(Object proxy, final Method method, final Object[] args) throws Throwable {
delayedInvocations.add(new Callable<Object>() {
@Override
public Object call() throws Exception {
return MethodUtils.invokeMethod(ext, method.getName(), args);
}
});
return null;
}
}
이제 우리는 어딘가에 얻고있다 : 대신의 방법 우리가
Callable
내부의 전화를 포장하고
delayedInvocations
큐에 추가를 호출. 물론 실제 메소드를 호출하지 않으므로 반환 값은 단지 자리 표시 자일뿐입니다.
ExternalClass
메서드의 반환 유형이
void
이 아닌 경우 매우주의해야합니다.
나는 지금 당신이 빛을 볼 것 같아요. 필요한 모든 것은 Callable
을 대기열에 모으고 일괄 적으로 실행하는 스레드를 만드는 것입니다. 다양한 방법으로 할 수 있지만 기본적인 빌딩 블록이 있습니다. 또한 맵과 같은 데이터 구조를 선택하거나 큐가 아닌 집합을 선택할 수도 있습니다. 예를 들어 어떤 이유로 든 이름으로 그룹화 방법을 상상할 수 있습니다.
물론 AspectJ/Spring AOP를 사용할 수 있다면 전체 프록시 인프라 코드를 피할 수 있습니다. 그러나 기본 아이디어는 API만이 더 즐거울 것이라는 점만 같을 것입니다.
Iv'e는 내가 처분 할 수있는 ExternalClass 인터페이스가 있음을 설명하는 질문을 편집했습니다. – eitama