문서 에 따르면 :
[
java.lang.reflect.
]Proxy
는 동적 프록시 클래스 및 인스턴스를 생성하기위한 정적 메서드를 제공하며 이러한 메서드에 의해 생성 된 모든 동적 프록시 클래스의 수퍼 클래스이기도합니다.
(동적 프록시 생성을 담당 하는) newProxyMethod
메서드 에는 다음과 같은 서명이 있습니다.
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
불행히도 이것은 특정 인터페이스를 구현하는 대신 특정 추상 클래스 를 확장 하는 동적 프록시를 생성하는 것을 방지 합니다. 이것은 “모든 동적 프록시의 수퍼 클래스”를 고려 하여 다른 클래스가 수퍼 클래스가되는 것을 방지 하므로 의미 가 있습니다.java.lang.reflect.Proxy
따라서 특정 추상 클래스에서 상속java.lang.reflect.Proxy
하는 동적 프록시를 생성 하여 추상 메서드에 대한 모든 호출을 호출 핸들러로 리디렉션 할 수 있는 대안이 있습니까?
예를 들어 추상 클래스가 있다고 가정합니다 Dog
.
public abstract class Dog {
public void bark() {
System.out.println("Woof!");
}
public abstract void fetch();
}
다음을 수행 할 수있는 수업이 있습니까?
Dog dog = SomeOtherProxy.newProxyInstance(classLoader, Dog.class, h);
dog.fetch(); // Will be handled by the invocation handler
dog.bark(); // Will NOT be handled by the invocation handler
답변
Javassist (참조 ProxyFactory
) 또는 CGLIB를 사용하여 수행 할 수 있습니다 .
Javassist를 사용한 Adam의 예 :
나는 (Adam Paynter) Javassist를 사용하여이 코드를 작성했습니다.
ProxyFactory factory = new ProxyFactory();
factory.setSuperclass(Dog.class);
factory.setFilter(
new MethodFilter() {
@Override
public boolean isHandled(Method method) {
return Modifier.isAbstract(method.getModifiers());
}
}
);
MethodHandler handler = new MethodHandler() {
@Override
public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args) throws Throwable {
System.out.println("Handling " + thisMethod + " via the method handler");
return null;
}
};
Dog dog = (Dog) factory.create(new Class<?>[0], new Object[0], handler);
dog.bark();
dog.fetch();
다음 출력을 생성합니다.
씨! 메소드 핸들러를 통해 public abstract void mock.Dog.fetch () 처리
답변
이러한 경우에 할 수있는 일은 추상 클래스의 기존 메서드로 호출을 리디렉션하는 프록시 처리기를 갖는 것입니다.
물론 코드를 작성해야하지만 매우 간단합니다. 프록시를 만들려면 그에게 InvocationHandler
. 그런 다음 invoke(..)
호출 핸들러 의 메서드 에서 메서드 유형 만 확인하면 됩니다. 그러나주의하십시오. 추상 클래스의 선언 된 유형이 아닌 핸들러에 연결된 기본 객체에 대해 메서드 유형을 확인해야합니다.
개 클래스를 예로 들어 보면 호출 핸들러의 invoke 메소드 는 다음과 같을 수 있습니다 (.. well …이라는 기존의 연관된 dog 하위 클래스 포함 dog
).
public void invoke(Object proxy, Method method, Object[] args) {
if(!Modifier.isAbstract(method.getModifiers())) {
method.invoke(dog, args); // with the correct exception handling
} else {
// what can we do with abstract methods ?
}
}
하지만 궁금해하는 점이 dog
있습니다. 객체에 대해 이야기했습니다 . 그러나 Dog 클래스는 추상이므로 인스턴스를 만들 수 없으므로 기존 하위 클래스가 있습니다. 또한 Proxy 소스 코드를 철저히 조사한 결과 인터페이스를 나타내지 않는 Class 객체에 대해 Proxy를 생성 할 수 없음을 (Proxy.java:362에서) 발견 할 수 있습니다.
그래서 현실 과는 별도로 하고 싶은 일이 완벽하게 가능합니다.