Heim  >  Artikel  >  Java  >  Vertiefendes Verständnis des dynamischen Java-Proxys

Vertiefendes Verständnis des dynamischen Java-Proxys

高洛峰
高洛峰Original
2017-02-08 11:00:101271Durchsuche

Dynamischer Proxy von JAVA
Agent-Modus
Der Proxy-Modus ist ein häufig verwendetes Java-Entwurfsmuster. Sein Merkmal besteht darin, dass die Proxy-Klasse und die Delegate-Klasse dieselbe Schnittstelle haben. Die Proxy-Klasse ist hauptsächlich für die Vorverarbeitung von Nachrichten verantwortlich und Filtern für die Delegatklasse-Nachricht, Weiterleiten der Nachricht an die Delegatenklasse und anschließendes Verarbeiten der Nachricht usw. Normalerweise besteht eine Assoziation zwischen einer Proxy-Klasse und einer Delegate-Klasse. Das Objekt der Proxy-Klasse selbst implementiert den Dienst nicht, sondern durch den Aufruf der entsprechenden Methoden des Objekts der Delegate-Klasse bestimmte Dienste bereitstellen.
Je nach Erstellungszeitraum des Agenten können Agentenklassen in zwei Typen unterteilt werden.
Statischer Proxy: Von Programmierern erstellt oder automatisch von bestimmten Tools generiert und dann kompiliert. Bevor das Programm ausgeführt wird, ist die .class-Datei der Proxy-Klasse bereits vorhanden.
Dynamischer Proxy: Wird mithilfe des Reflexionsmechanismus dynamisch erstellt, wenn das Programm ausgeführt wird.

Erster Blick auf den statischen Proxy:

1. Count.java

package net.battier.dao;  
  
/** 
 * 定义一个账户接口 
 *  
 * @author Administrator 
 *  
 */  
public interface Count {  
    // 查看账户方法  
    public void queryCount();  
  
    // 修改账户方法  
    public void updateCount();  
  
}

2. CountImpl.java

package net.battier.dao.impl;  
  
import net.battier.dao.Count;  
  
/** 
 * 委托类(包含业务逻辑) 
 *  
 * @author Administrator 
 *  
 */  
public class CountImpl implements Count {  
  
    @Override  
    public void queryCount() {  
        System.out.println("查看账户方法...");  
  
    }  
  
    @Override  
    public void updateCount() {  
        System.out.println("修改账户方法...");  
  
    }  
  
}  
  
、CountProxy.java  
package net.battier.dao.impl;  
  
import net.battier.dao.Count;  
  
/** 
 * 这是一个代理类(增强CountImpl实现类) 
 *  
 * @author Administrator 
 *  
 */  
public class CountProxy implements Count {  
    private CountImpl countImpl;  
  
    /** 
     * 覆盖默认构造器 
     *  
     * @param countImpl 
     */  
    public CountProxy(CountImpl countImpl) {  
        this.countImpl = countImpl;  
    }  
  
    @Override  
    public void queryCount() {  
        System.out.println("事务处理之前");  
        // 调用委托类的方法;  
        countImpl.queryCount();  
        System.out.println("事务处理之后");  
    }  
  
    @Override  
    public void updateCount() {  
        System.out.println("事务处理之前");  
        // 调用委托类的方法;  
        countImpl.updateCount();  
        System.out.println("事务处理之后");  
  
    }  
  
}

3. TestCount.java

package net.battier.test;  
  
import net.battier.dao.impl.CountImpl;  
import net.battier.dao.impl.CountProxy;  
  
/** 
 *测试Count类 
 *  
 * @author Administrator 
 *  
 */  
public class TestCount {  
    public static void main(String[] args) {  
        CountImpl countImpl = new CountImpl();  
        CountProxy countProxy = new CountProxy(countImpl);  
        countProxy.updateCount();  
        countProxy.queryCount();  
  
    }  
}

Wenn Sie den Code beobachten, können Sie feststellen, dass jede Proxy-Klasse nur eine Schnittstelle bedienen kann. Auf diese Weise werden während der Programmentwicklung zwangsläufig zu viele Proxys generiert alle Proxys Mit Ausnahme der aufgerufenen Methode sind alle anderen Vorgänge gleich, daher muss der Code zu diesem Zeitpunkt wiederholt werden. Der beste Weg, dieses Problem zu lösen, besteht darin, eine Proxy-Klasse zum Abschließen aller Proxy-Funktionen zu verwenden. In diesem Fall muss ein dynamischer Proxy zum Abschließen verwendet werden.
Werfen wir einen Blick auf den dynamischen Proxy:
Der dynamische JDK-Proxy enthält eine Klasse und eine Schnittstelle:
InvocationHandler-Schnittstelle:

public interface InvocationHandler { 
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable; 
}

Parameterbeschreibung:
Objekt-Proxy: verweist zum Proxy-Objekt.
Methodenmethode: die aufzurufende Methode
Objekt[]-Argumente: die beim Aufruf der Methode erforderlichen Parameter

Sie können sich die Unterklasse der InvocationHandler-Schnittstelle als die letzte Operationsklasse eines Proxys vorstellen. ersetzt ProxySubject .

Proxy-Klasse:
Die Proxy-Klasse ist eine auf Proxy-Operationen spezialisierte Klasse, die über diese Klasse dynamisch für eine oder mehrere Schnittstellen generiert werden kann:
öffentliches statisches Objekt newProxyInstance(ClassLoader-Loader, Class6b3d0130bba23ae47fe2b8e8cddf0195[]-Schnittstellen,
InvocationHandler h)
 🎜>ClassInvocationHandler h: die Unterklasse abrufen Instanz der InvocationHandler-Schnittstelle

Ps: Klassenlader
Eine ClassLoader-Klasse ist in der newProxyInstance()-Methode in der Proxy-Klasse erforderlich. Instanzen von ClassLoader entsprechen tatsächlich Klassenladern. In Java gibt es drei Hauptklassenlader ;

Booststrap ClassLoader: Dieser Loader ist in C++ geschrieben und kann in der allgemeinen Entwicklung nicht angezeigt werden;

Erweiterung ClassLoader: wird zum Laden erweiterter Klassen verwendet, die im Allgemeinen den Klassen im jrelibext-Verzeichnis entsprechen; ) lädt die durch den Klassenpfad angegebene Klasse, den am häufigsten verwendeten Lader.

Dynamischer Proxy
Im Gegensatz zur statischen Proxy-Klasse wird der Bytecode der dynamischen Proxy-Klasse dynamisch durch den Java-Reflektionsmechanismus generiert, wenn das Programm ausgeführt wird, ohne dass Programmierer dies tun müssen Schreiben Sie den Quellcode manuell. Dynamische Proxy-Klassen vereinfachen nicht nur die Programmierarbeit, sondern verbessern auch die Skalierbarkeit von Softwaresystemen, da der Java-Reflexionsmechanismus jede Art von dynamischen Proxy-Klassen generieren kann. Die Proxy-Klasse und die InvocationHandler-Schnittstelle im Paket java.lang.reflect bieten die Möglichkeit, dynamische Proxy-Klassen zu generieren.

Dynamisches Proxy-Beispiel:


1. BookFacadeImpl.java

3 🎜>

Der dynamische Proxy von JDK basiert jedoch auf der Schnittstellenimplementierung. Wenn einige Klassen die Schnittstelle nicht implementieren, kann der JDK-Proxy nicht verwendet werden, daher muss der dynamische Proxy von cglib verwendet werden.
package net.battier.dao;  
  
public interface BookFacade {  
    public void addBook();  
}

Dynamischer Proxy von Cglib

Der dynamische Proxy-Mechanismus von JDK kann nur Proxy-Klassen implementieren, die keine Schnittstellen implementieren können. Der dynamische Proxy von JDK kann nicht implementiert werden. Das Prinzip besteht darin, eine Unterklasse für zu generieren die angegebene Zielklasse und überschreiben Sie die Methoden, um eine Erweiterung zu erreichen. Da jedoch Vererbung verwendet wird, kann die endgültige geänderte Klasse nicht als Proxy verwendet werden.
package net.battier.dao.impl;  
  
import net.battier.dao.BookFacade;  
  
public class BookFacadeImpl implements BookFacade {  
  
    @Override  
    public void addBook() {  
        System.out.println("增加图书方法。。。");  
    }  
  
}  
  
、BookFacadeProxy.java  
  
package net.battier.proxy;  
  
import java.lang.reflect.InvocationHandler;  
import java.lang.reflect.Method;  
import java.lang.reflect.Proxy;  
  
/** 
 * JDK动态代理代理类 
 *  
 * @author student 
 *  
 */  
public class BookFacadeProxy implements InvocationHandler {  
    private Object target;  
    /** 
     * 绑定委托对象并返回一个代理类 
     * @param target 
     * @return 
     */  
    public Object bind(Object target) {  
        this.target = target;  
        //取得代理对象  
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),  
                target.getClass().getInterfaces(), this);   //要绑定接口(这是一个缺陷,cglib弥补了这一缺陷)  
    }  
  
    @Override  
    /** 
     * 调用方法 
     */  
    public Object invoke(Object proxy, Method method, Object[] args)  
            throws Throwable {  
        Object result=null;  
        System.out.println("事物开始");  
        //执行方法  
        result=method.invoke(target, args);  
        System.out.println("事物结束");  
        return result;  
    }  
  
}
Beispiel

1. BookFacadeCglib.java
package net.battier.test;  
  
import net.battier.dao.BookFacade;  
import net.battier.dao.impl.BookFacadeImpl;  
import net.battier.proxy.BookFacadeProxy;  
  
public class TestProxy {  
  
    public static void main(String[] args) {  
        BookFacadeProxy proxy = new BookFacadeProxy();  
        BookFacade bookProxy = (BookFacade) proxy.bind(new BookFacadeImpl());  
        bookProxy.addBook();  
    }  
  
}

2. BookCadeImpl1.java



3. BookFacadeProxy.java

4. TestCglib.java
package net.battier.dao;  
  
public interface BookFacade {  
    public void addBook();  
}

Für ein tieferes Verständnis der Artikel zum Thema Java Dynamic Proxy beachten Sie bitte die chinesische PHP-Website!
package net.battier.dao.impl;  
  
/** 
 * 这个是没有实现接口的实现类 
 *  
 * @author student 
 *  
 */  
public class BookFacadeImpl1 {  
    public void addBook() {  
        System.out.println("增加图书的普通方法...");  
    }  
}
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:Verständnis von SpringAOPNächster Artikel:Verständnis von SpringAOP