>  기사  >  Java  >  자바 프록시 모드와 동적 프록시 모드에 대한 자세한 설명

자바 프록시 모드와 동적 프록시 모드에 대한 자세한 설명

高洛峰
高洛峰원래의
2017-02-07 13:40:281138검색

1. 에이전시 모델

소위 에이전시란 다른 사람이나 다른 조직을 대신하여 행동하는 개인이나 조직입니다. 어떤 경우에는 클라이언트가 개체를 직접 참조하는 것을 원하지 않거나 참조할 수 없으며 프록시 개체가 클라이언트와 대상 개체 사이의 중개자 역할을 할 수 있습니다.
프록시 모드는 객체에 대한 프록시 객체를 제공하고, 프록시 객체는 원본 객체에 대한 참조를 제어합니다.

실생활의 예: 저는 설 연휴에 야근을 하느라 바빠서 기차표를 살 시간이 없습니다. 이때 근처 매표소에 전화해서 기차표를 사달라고 부탁하면 됩니다. 물론 집에 가려면 추가 인건비가 부과됩니다. 그러나 티켓 센터 자체가 티켓을 판매하는 것은 아니며, 실제로 기차역에서만 티켓을 판매합니다. 티켓 센터가 판매하는 티켓은 실제로 기차역을 통해 실현됩니다. 이것은 매우 중요합니다!

위의 예에서 당신은 "고객", 티켓 센터는 "대리인 역할", 기차역은 "실제 역할", 티켓 판매는 "추상적 역할"이라고 합니다!


에이전트 모드 JAVA 코드 예:
추상 역할: 추상 클래스 또는 인터페이스

interface Business  
{  
    void doAction();  
}

실제 역할: 비즈니스 로직 인터페이스를 실제로 구현

프록시 역할: 비즈니스 로직 인터페이스를 구현하지는 않았지만

class BusinessImplProxy implements Business  
{  
    private BusinessImpl bi;  
    public void doAction()  
    {  
        if (bi==null)  
        {  
            bi = new BusinessImpl();  
        }  
        doBefore();  
        bi.doAction();  
        doAfter();  
    }  
    public void doBefore()  
    {  
        System.out.println("前置处理!");  
    }  
    public void doAfter()  
    {  
        System.out.println("后置处理!");  
    }  
}  
//测试类  
class Test  
{  
    public static void main(String[] args)  
    {  
        //引用变量定义为抽象角色类型  
        Business bi = new BusinessImplProxy();  
        bi.doAction();  
    }  
}
<span></span>

를 구현하기 위해 실제 역할을 호출했습니다. 따라서 JVM의 지원으로 프록시 클래스("에이전트 역할")가 런타임에 동적으로 생성될 수 있으며, 위의 문제를 해결하십시오. 프록시 모드에서 코드 팽창 문제를 해결하려면 동적 프록시를 사용한 후 "에이전트 역할"이 수동으로 생성되지 않고 세 가지 매개변수(클래스 로더, 클래스 로더, 인터페이스 배열 및 호출 처리기.

동적 프록시 모드 JAVA 코드 예:

import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Proxy;
 import java.lang.reflect.Method;
 //抽象角色:java动态代理的实现目前只支持接口,不支持抽象类
 interface BusinessFoo
 {
     void foo();
 }
 interface BusinessBar
{
    String bar(String message);
}
//真实角色:真正实现业务逻辑方法
class BusinessFooImpl implements BusinessFoo
{
    public void foo()
    {
        System.out.println("BusinessFooImpl.foo()");
    }
}
class BusinessBarImpl implements BusinessBar
{
    public String bar(String message)
    {
        System.out.println("BusinessBarImpl.bar()");
        return message;
    }
}
//动态角色:动态生成代理类
class BusinessImplProxy implements InvocationHandler
{
    private Object obj;
    BusinessImplProxy() {
    }
    BusinessImplProxy(Object obj) {
        this.obj = obj;
    }
    public Object invoke(Object proxy,Method method,Object[] args) throws Throwable
    {
        Object result = null;
        doBefore();
        result = method.invoke(obj,args);
        doAfter();
        return result;
    }
    public void doBefore(){
        System.out.println("do something before Business Logic");
    }
    public void doAfter(){
        System.out.println("do something after Business Logic");
    }
    public static Object factory(Object obj)
    {
        Class cls = obj.getClass();
        return Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(),new BusinessImplProxy(obj));
    }
}
//测试类
public class DynamicProxy
{    
    public static void main(String[] args) throws 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);
        String message = bb.bar("Hello,World");
        System.out.println(message);
    }
}

프로그램 흐름 설명:
new BusinessFooImpl()은 "실제 역할"을 생성하고 이를 팩토리 메소드 BusinessImplProxy.factory()에 전달합니다. 을 클릭한 다음 InvocationHandler를 구현하는 클래스인 "호출 핸들러"를 초기화합니다. 그리고 동적으로 생성된 프록시 클래스 인스턴스를 반환합니다. "에이전트 역할"은 "추상 역할"에서 제공하는 비즈니스 로직 메서드도 구현해야 하므로 BusinessBar로 변환되고 BusinessBar 유형을 가리키는 참조 bb에 할당될 수 있습니다.
newProxyInstance(ClassLoader loader, Class6b3d0130bba23ae47fe2b8e8cddf0195[] 인터페이스, InvocationHandler h) 메소드를 사용하면 프로그래머가 매개변수를 지정하고 필요한 프록시 클래스를 동적으로 반환할 수 있으며, Invoke(Object Proxy, Method method, Object[] args) 메소드 런타임 시 JVM에 의해 동적으로 호출됩니다. "bb.bar("Hello,World");" 메소드가 실행되면 JVM은 "호출 프로세서"를 동적으로 할당하고 매개변수를 외부 호출에 전달하고 method.invoke(obj, args)를 호출하여 실제로 실행합니다. !

BusinessImplProxy.Factory 정적 메소드는 프록시 클래스("에이전트 역할")를 동적으로 생성하는 데 사용됩니다. 다양한 비즈니스 로직 인터페이스인 BusinessFoo 및 BusinessBar에 따라 프록시 역할은 런타임에 동적으로 생성됩니다. "추상 역할", "에이전트 역할" 및 호출 핸들러(InvocationHandler 인터페이스를 구현하는 클래스)를 모두 변경할 수 있으므로 JAVA의 동적 프록시는 매우 강력합니다.

Java 프록시 모드와 동적 프록시 모드에 대한 자세한 설명은 PHP 중국어 홈페이지를 참고해주세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.