Heim  >  Artikel  >  Java  >  Dynamischer Proxy für Entwurfsmuster

Dynamischer Proxy für Entwurfsmuster

巴扎黑
巴扎黑Original
2017-06-26 09:35:481165Durchsuche

1. Dynamisches Proxy-Konzept

Dynamischer Proxy ist in zwei Methoden unterteilt: dynamischer JDK-Proxy und dynamischer cglib-Proxy.

Der dynamische JDK-Proxy wird durch den internen Reflexionsmechanismus von Java implementiert, während die unterste Ebene des dynamischen cglib-Proxys mithilfe von ASM implementiert wird.

Im Allgemeinen ist der Reflexionsmechanismus beim Generieren von Klassen effizienter, während ASM im zugehörigen Ausführungsprozess nach dem Generieren der Klasse effizienter ist (Sie können die von ASM generierten Klassen zwischenspeichern, um das Problem zu lösen Probleme mit der ASM-Generierung (Prozessineffizienz).

Es gibt noch einen weiteren Punkt, der beachtet werden muss: Voraussetzung für die Anwendung des dynamischen JDK-Proxys muss sein, dass die Zielklasse auf einer einheitlichen Schnittstelle basiert. Ohne die oben genannten Voraussetzungen kann der dynamische JDK-Proxy nicht angewendet werden.

Daraus ist ersichtlich, dass der dynamische JDK-Proxy bestimmte Einschränkungen aufweist. Dynamische Proxys, die von Klassenbibliotheken von Drittanbietern wie cglib implementiert werden, werden häufiger verwendet und bieten mehr Effizienzvorteile.

2. Dynamischer JDK-Proxy

Der folgende Code verwendet den Proxy-Modus, um eine Funktion zum Konvertieren von Groß- und Kleinbuchstaben zu implementieren.

Definition der Schnittstelle und Implementierungsklasse:

ISomeService-Schnittstelle:

package com.ietree.basicskill.designpattern.dynamicproxy.jdk;/**
 * 接口类
 * 
 * @author Root */public interface ISomeService {
    
    String doFirst();    void doSecond();
}

SomeServiceImpl-Implementierungsklasse:

package com.ietree.basicskill.designpattern.dynamicproxy.jdk;/**
 * 实现类
 * 
 * @author Root */public class SomeServiceImpl implements ISomeService {

    @Overridepublic String doFirst() {
        System.out.println("执行doFirst()...");
        String result = "abcde";return result;
    }

    @Overridepublic void doSecond() {
        System.out.println("执行doSecond()...");
    }

}

Dynamische JDK-Proxy-Klasse:

package com.ietree.basicskill.designpattern.dynamicproxy.jdk;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class Main {public static void main(String[] args) {final ISomeService target = new SomeServiceImpl();        // 使用JDK的Proxy动态代理,要求目标类和代理类必须实现相同的接口,因为其底层的执行原理与静态代理的相同ISomeService service = (ISomeService) Proxy.newProxyInstance(// 目标类的类加载器                target.getClass().getClassLoader(),// 目标类所实现的所有接口                target.getClass().getInterfaces(), new InvocationHandler() {// proxy:代理对象// method:目标方法// args:目标方法的参数列表                    @Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 调用目标方法Object result = method.invoke(target, args);if (result != null) {
                            result = ((String) result).toUpperCase();
                        }return result;
                    }
                });
        String result = service.doFirst();
        System.out.println(result);

        service.doSecond();
    }
}

3. cglib dynamischer Proxy

Cglib ist ein ausgezeichnetes dynamisches Proxy-Framework, dessen unterste Ebene verwendet wird ASM generiert dynamisch Unterklassen der Proxy-Klasse im Speicher und implementiert dynamische Proxy-Funktionen mit CGLIB, auch wenn die Proxy-Klasse keine Schnittstelle implementiert. CGLIB ist einfach und benutzerfreundlich und läuft viel schneller als der dynamische Proxy-Proxy von JDK:

CGLIBs Kernklasse:
net.sf.cglib.proxy.Enhancer – die Haupterweiterungsklasse
net .sf.cglib.proxy.MethodInterceptor – die Hauptklasse zum Abfangen von Methoden, die eine Unterschnittstelle der Callback-Schnittstelle ist und von Benutzern die Implementierung von
net.sf.cglib.proxy.MethodProxy – java.lang.reflect des JDK erfordert. Die Proxy-Klasse der Method-Klasse kann bequem die Methode des Quellobjekts aufrufen, beispielsweise mit:
Object o = methodProxy.invokeSuper(proxy, args);//Obwohl der erste Parameter das Proxy-Objekt ist, wird er nicht unendlich sein Es tritt ein Schleifenproblem auf.

Die Schnittstelle net.sf.cglib.proxy.MethodInterceptor ist der gebräuchlichste Rückruftyp. Sie wird häufig von Proxy-basierten AOP zum Implementieren von Intercept-Methodenaufrufen verwendet. Diese Schnittstelle definiert nur eine Methode
public Object intercept(Object object, java.lang.reflect.Method method, Object[] args, MethodProxy Proxy) throws Throwable;

Der erste Parameter ist das Proxy-Paar Like , der zweite und der dritte Parameter sind die abgefangenen Methoden- bzw. Methodenparameter. Die ursprüngliche Methode kann durch normale Reflektion mit einem java.lang.reflect.Method-Objekt oder mit einem net.sf.cglib.proxy.MethodProxy-Objekt aufgerufen werden. net.sf.cglib.proxy.MethodProxy wird normalerweise bevorzugt, da es schneller ist.

Das folgende Programm implementiert die Fallkonvertierungsfunktion:

Implementierungsklasse SomeService:

package com.ietree.basicskill.designpattern.dynamicproxy.cglib;/**
 * 实现类
 * 
 * @author Root */public class SomeService {public String doFirst() {
        System.out.println("执行doFirst()...");
        String result = "abcde";return result;
    }public void doSecond() {
        System.out.println("执行doSecond()...");
    }

}

Proxyklasse MyCglibFactory:

package com.ietree.basicskill.designpattern.dynamicproxy.cglib;import java.lang.reflect.Method;import net.sf.cglib.proxy.Enhancer;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;public class MyCglibFactory implements MethodInterceptor {private SomeService target;    public MyCglibFactory() {super();
        target = new SomeService();
    }public SomeService myCglibCreator() {// 创建增强器对象Enhancer enhancer = new Enhancer();// 指定目标类,即父类enhancer.setSuperclass(SomeService.class);// 设置回调接口对象enhancer.setCallback(this);return (SomeService) enhancer.create();
    }

    @Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {// 调用目标方法Object result = method.invoke(target, args);if (result != null) {
            result = ((String) result).toUpperCase();
        }return result;
    }

}

Test:

package com.ietree.basicskill.designpattern.dynamicproxy.cglib;public class Main {public static void main(String[] args) {

        SomeService service = new MyCglibFactory().myCglibCreator();
        
        String result = service.doFirst();
        System.out.println("result = " + result);

        service.doSecond();
    }
}

Laufergebnis:

执行doFirst()...
result = ABCDE
执行doSecond()...

Das obige ist der detaillierte Inhalt vonDynamischer Proxy für Entwurfsmuster. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Vorheriger Artikel:Designmuster einfache FabrikNächster Artikel:Designmuster einfache Fabrik