1. 에이전트 모드
대리인은 다른 사람이나 기관을 대신하여 행동하는 사람이나 기관입니다. 어떤 경우에는 클라이언트가 개체를 직접 참조하는 것을 원하지 않거나 참조할 수 없으며 프록시 개체가 클라이언트와 대상 개체 사이의 중개자 역할을 할 수 있습니다.
프록시 패턴은 객체에 대한 프록시 객체를 제공하고 프록시 객체는 원본 객체에 대한 참조를 제어합니다.
실생활의 예: 새해에 야근을 하느라 기차표를 살 시간이 없습니다. 이때 근처 티켓 센터에 전화해서 집으로 가는 기차표를 사달라고 요청할 수 있습니다. 추가 인건비를 추가하세요. 그러나 티켓 센터 자체가 티켓을 판매하는 것은 아니며, 실제로 기차역에서만 티켓을 판매합니다. 티켓 센터가 판매하는 티켓은 실제로 기차역을 통해 실현됩니다. 이것은 매우 중요합니다!
위의 예에서 귀하는 "고객"이고, 티켓 센터는 "대리인 역할", 기차역은 "실제 역할", 티켓 판매는 "추상적 역할"이라고 합니다!
에이전트 모드 JAVA 코드 예:
추상 역할: 추상 클래스 또는 인터페이스
다음과 같이 코드 코드를 복사합니다.
인터페이스비즈니스
{
무효 doAction();
}
실제 역할: 비즈니스 로직 인터페이스를 실제로 구현합니다.
에이전트 역할: 비즈니스 로직 인터페이스를 구현하지 않지만 이를 구현하기 위해 실제 역할을 호출합니다.
다음과 같이 코드 코드를 복사합니다.
BusinessImplProxy 클래스는 비즈니스를 구현합니다.
{
개인 BusinessImpl bi;
공공 무효 doAction()
{
if (bi==null)
{
bi = 새로운 BusinessImpl();
}
doBefore();
bi.doAction();
doAfter();
}
공공 무효 doBefore()
{
System.out.println("전처리 중!");
}
공공 무효 doAfter()
{
System.out.println("후처리 중입니다!");
}
}
//테스트 클래스
수업 테스트
{
공개 정적 무효 메인(문자열[] 인수)
{
//참조 변수는 추상 역할 유형으로 정의됩니다.
비즈니스 bi = new BusinessImplProxy();
bi.doAction();
}
}
다음과 같이 코드 코드를 복사합니다.
<스팬></스팬>
따라서 JVM의 지원을 통해 프록시 클래스("에이전트 역할")가 런타임에 동적으로 생성될 수 있으며 위의 프록시 모드에서 코드 확장 문제를 해결할 수 있습니다. 동적 프록시를 사용한 후에는 "에이전트 역할"이 필요하지 않습니다. 클래스 로더, 인터페이스 배열 및 호출 핸들러라는 세 가지 매개변수를 지정하여 런타임 시 JVM에 의해 동적으로 생성됩니다.
동적 프록시 모드 JAVA 코드 예:
다음과 같이 코드 코드를 복사합니다.
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.lang.reflect.Method;
//추상 역할: Java 동적 프록시 구현은 현재 인터페이스만 지원하고 추상 클래스는 지원하지 않습니다.
인터페이스 BusinessFoo
{
무효 foo();
}
인터페이스비즈니스바
{
스트링바(문자열 메시지);
}
//실제 역할: 실제로 비즈니스 로직 메소드를 구현합니다.
BusinessFooImpl 클래스는 BusinessFoo를 구현합니다.
{
공공 무효 foo()
{
System.out.println("BusinessFooImpl.foo()");
}
}
BusinessBarImpl 클래스는 BusinessBar를 구현합니다.
{
공개 스트링 바(문자열 메시지)
{
System.out.println("BusinessBarImpl.bar()");
반환 메시지;
}
}
//동적 역할: 프록시 클래스를 동적으로 생성합니다.
BusinessImplProxy 클래스는 InvocationHandler를 구현합니다.
{
privateObject obj;
비즈니스ImplProxy() {
}
BusinessImplProxy(객체 obj) {
this.obj = obj;
}
공용 개체 호출(개체 프록시, 메서드 메서드, 개체[] args)에서 Throwable이 발생합니다.
{
개체 결과 = null;
doBefore();
결과 = method.invoke(obj,args);
doAfter();
결과 반환;
}
공공 무효 doBefore(){
System.out.println("비즈니스 로직 이전에 작업 수행");
}
공공 무효 doAfter(){
System.out.println("비즈니스 로직 다음에 뭔가를 하세요");
}
공개 정적 객체 팩토리(객체 obj)
{
클래스 cls = obj.getClass();
return Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(),new BusinessImplProxy(obj));
}
}
//테스트 클래스
공개 클래스 DynamicProxy
{
public static void main(String[] args)에서 Throwable이 발생합니다.
{
BusinessFooImpl bfoo = new BusinessFooImpl();
BusinessFoo bf = (BusinessFoo)BusinessImplProxy.factory(bfoo);
bf.foo();
System.out.println();
BusinessBarImpl bbar = new BusinessBarImpl();
BusinessBar bb = (BusinessBar)BusinessImplProxy.factory(bbar);
문자열 메시지 = bb.bar("Hello,World");
System.out.println(메시지);
}
}
프로그램 흐름 설명:
new BusinessFooImpl(); "실제 역할"을 생성하고 이를 팩토리 메소드 BusinessImplProxy.factory()에 전달한 다음 InvocationHandler를 구현하는 클래스인 "호출 프로세서"를 초기화합니다. 그리고 동적으로 생성된 프록시 클래스 인스턴스를 반환합니다. "에이전트 역할"은 "추상 역할"에서 제공하는 비즈니스 로직 메서드도 구현해야 하므로 BusinessBar로 변환되고 BusinessBar 유형을 가리키는 참조 bb에 할당될 수 있습니다.
newProxyInstance(ClassLoader 로더, Class<?>[] 인터페이스, InvocationHandler h) 메소드를 사용하면 프로그래머가 매개변수를 지정하고 필요한 프록시 클래스를 동적으로 반환할 수 있으며, 호출(Object 프록시, 메소드 메소드, Object[] args) 메소드는 다음에서 사용됩니다. JVM은 런타임에 동적으로 호출됩니다. "bb.bar("Hello,World");" 메소드가 실행되면 JVM은 "호출 프로세서"를 동적으로 할당하고 매개변수를 외부 호출에 전달하고 method.invoke(obj, args)를 호출하여 실제로 실행합니다. !
BusinessImplProxy.Factory 정적 메소드는 프록시 클래스("에이전트 역할")를 동적으로 생성하는 데 사용됩니다. 프록시 역할은 다양한 비즈니스 로직 인터페이스인 BusinessFoo 및 BusinessBar를 기반으로 런타임에 동적으로 생성됩니다. "추상 역할", "에이전트 역할" 및 호출 핸들러(InvocationHandler 인터페이스를 구현하는 클래스)를 모두 변경할 수 있으므로 JAVA의 동적 프록시는 매우 강력합니다.