Heim  >  Artikel  >  Java  >  Was sind die drei Proxy-Modi von Java?

Was sind die drei Proxy-Modi von Java?

王林
王林nach vorne
2021-01-30 09:44:052385Durchsuche

Was sind die drei Proxy-Modi von Java?

Erklären wir zunächst kurz, was das Agenturmodell ist.

Proxy ist ein Entwurfsmuster, das eine weitere Möglichkeit bietet, auf das Zielobjekt zuzugreifen, d. Das heißt, die Funktion des Zielobjekts zu erweitern.
Eine Idee in der Programmierung wird hier verwendet: Ändern Sie den Code oder die Methoden, die von anderen geschrieben wurden, nicht nach Belieben. Wenn Sie Änderungen vornehmen müssen, können Sie die Methode durch a erweitern Proxy

Um die Rolle eines Agenten zu veranschaulichen: Angenommen, wir möchten einen Star einladen, dann kontaktieren wir den Star nicht direkt, sondern kontaktieren den Agenten des Stars, um den gleichen Zweck zu erreichen. Der Star ist ein Zielobjekt, nur er muss für das Programm in der Veranstaltung verantwortlich sein, und die Lösung anderer trivialer Angelegenheiten wird seinem Agenten (Makler) überlassen. Dies ist ein Beispiel für Agenturdenken in der Realität. Es wird durch ein Diagramm wie folgt dargestellt:

Was sind die drei Proxy-Modi von Java?Der Kernpunkt des Agenturmodells ist: Das Proxy-Objekt und das Zielobjekt sind eine Erweiterung des Zielobjekts und rufen den statischen Proxy auf Definieren Sie eine Schnittstelle oder übergeordnete Klasse, und das Proxy-Objekt implementiert dieselbe Schnittstelle oder erbt dieselbe übergeordnete Klasse.

Das Folgende ist ein Beispiel zur Erläuterung:

Simulieren Sie die Speicheraktion und definieren Sie eine Schnittstelle für die Speicheraktion : IUserDao.java, und dann implementiert das Zielobjekt die Methode UserDao.java dieser Schnittstelle. Wenn Sie zu diesem Zeitpunkt die statische Proxy-Methode verwenden, müssen Sie die IUserDao-Schnittstelle im Proxy-Objekt (UserDaoProxy.java) implementieren Rufen Sie beim Aufrufen die Methode des Proxy-Objekts auf, um das Zielobjekt aufzurufen. Beachten Sie, dass das Proxy-Objekt und das Zielobjekt dieselbe Schnittstelle implementieren und dann dieselbe Methode aufrufen müssen, um die Methode des Zielobjekts aufzurufen

Codebeispiel:

Schnittstelle: IUserDao.java

/**
 * 接口
 */public interface IUserDao {    void save();
}

Zielobjekt: UserDao.java

/**
 * 接口实现
 * 目标对象
 */public class UserDao implements IUserDao {    public void save() {
        System.out.println("----已经保存数据!----");
    }
}

Proxy-Objekt: UserDaoProxy.java
/**
 * 代理对象,静态代理
 */public class UserDaoProxy implements IUserDao{    //接收保存目标对象
    private IUserDao target;    public UserDaoProxy(IUserDao target){        this.target=target;
    }    public void save() {
        System.out.println("开始事务...");
        target.save();//执行目标对象的方法
        System.out.println("提交事务...");
    }
}

(Lernvideo-Sharing:

Java-Video-Tutorial
)

Testklasse: App. Java

/**
 * 测试类
 */public class App {    public static void main(String[] args) {        //目标对象
        UserDao target = new UserDao();        //代理对象,把目标对象传给代理对象,建立代理关系
        UserDaoProxy proxy = new UserDaoProxy(target);

        proxy.save();//执行的是代理的方法
    }
}

Statische Proxy-Zusammenfassung:

1. Die Zielfunktion kann erweitert werden, ohne die Funktion des Zielobjekts zu ändern.

2 Nachteile:Da das Proxy-Objekt dieselbe Schnittstelle wie das Zielobjekt implementieren muss, wird es eine geben Viele Proxy-Klassen, zu viele Klassen. Sobald die Schnittstelle Methoden hinzufügt, müssen sowohl das Zielobjekt als auch das Proxy-Objekt beibehalten werden.

Wie können die Mängel statischer Proxys behoben werden? Proxy-Methode

1.2. Dynamischer Proxy

Dynamischer Proxy hat die folgenden Eigenschaften:

1. Bei der Generierung des Proxy-Objekts wird die API von JDK verwendet, um das Proxy-Objekt dynamisch zu erstellen im Speicher (Wir müssen den Typ der Schnittstelle angeben, um ein zu implementierendes Proxy-Objekt/Zielobjekt zu erstellen)

3 Dynamischer Proxy wird auch genannt: JDK-Proxy, Schnittstellen-Proxy

API zum Generieren von Proxy-Objekten im JDK

Das Paket wo Die Proxy-Klasse befindet sich: java.lang.reflect.Proxy

JDK muss nur die newProxyInstance-Methode verwenden, um den Proxy zu implementieren, aber diese Methode muss drei Parameter empfangen. Die vollständige Schreibmethode lautet:

static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h )

Beachten Sie, dass diese Methode vorhanden ist eine statische Methode in der Proxy-Klasse, und die drei empfangenen Parameter sind in der Reihenfolge:

ClassLoader-Loader: Gibt an, dass das aktuelle Zielobjekt einen Klassenlader verwendet. Die Methode zum Abrufen des Loaders ist festgelegt

Class>[. ] Schnittstellen: Der vom Zielobjekt implementierte Schnittstellentyp. Verwenden Sie Generika, um den Typ zu bestätigen des aktuell ausgeführten Zielobjekts wird als Parameter übergeben. Java), schreiben Sie hier die Proxy-Klasse und erstellen Sie dann das Zielobjekt in der Testklasse (Code, der den Proxy verwenden muss). Kontaktieren Sie das Proxy-Objekt und verwenden Sie dann die gleichnamige Methode im Proxy-Objekt


Proxy-Factory Klasse: ProxyFactory.java

/**
 * 创建动态代理对象
 * 动态代理不需要实现接口,但是需要指定接口类型
 */public class ProxyFactory{    //维护一个目标对象
    private Object target;    public ProxyFactory(Object target){        this.target=target;
    }   //给目标对象生成代理对象
    public Object getProxyInstance(){        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),                new InvocationHandler() {                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("开始事务2");                        //执行目标对象方法
                        Object returnValue = method.invoke(target, args);
                        System.out.println("提交事务2");                        return returnValue;
                    }
                }
        );
    }

}

Testklasse: App.java

/**
 * 测试类
 */public class App {    public static void main(String[] args) {        // 目标对象
        IUserDao target = new UserDao();        // 【原始的类型 class cn.itcast.b_dynamic.UserDao】
        System.out.println(target.getClass());        // 给目标对象,创建代理对象
        IUserDao proxy = (IUserDao) new ProxyFactory(target).getProxyInstance();        // class $Proxy0   内存中动态生成的代理对象
        System.out.println(proxy.getClass());        // 执行方法   【代理对象】
        proxy.save();
    }
}

Zusammenfassung:

Das Proxy-Objekt muss die Schnittstelle nicht implementieren, aber das Zielobjekt muss die Schnittstelle implementieren, sonst können Sie keinen dynamischen Proxy verwenden

1.3. Cglib-Proxy

Die oben genannten statischen Proxy- und dynamischen Proxy-Modi erfordern, dass das Zielobjekt das Zielobjekt ist, das eine Schnittstelle implementiert. Manchmal ist das Zielobjekt jedoch nur ein separates Objekt und es gibt keine Schnittstelle Zielobjekt-Unterklasse zum Implementieren des Proxys. Diese Methode heißt: Cglib-Proxy

Cglib代理,也叫作子类代理,它是在内存中构建一个子类对象从而实现对目标对象功能的扩展.

JDK的动态代理有一个限制,就是使用动态代理的对象必须实现一个或多个接口,如果想代理没有实现接口的类,就可以使用Cglib实现.Cglib是一个强大的高性能的代码生成包,它可以在运行期扩展java类与实现java接口.它广泛的被许多AOP的框架使用,例如Spring AOP和synaop,为他们提供方法的interception(拦截)Cglib包的底层是通过使用一个小而块的字节码处理框架ASM来转换字节码并生成新的类.不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉.

Cglib子类代理实现方法:
1.需要引入cglib的jar文件,但是Spring的核心包中已经包括了Cglib功能,所以直接引入pring-core-3.2.5.jar即可.
2.引入功能包后,就可以在内存中动态构建子类
3.代理的类不能为final,否则报错
4.目标对象的方法如果为final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法.

代码示例:
目标对象类:UserDao.java

/**
 * 目标对象,没有实现任何接口
 */public class UserDao {    public void save() {
        System.out.println("----已经保存数据!----");
    }
}

Cglib代理工厂:ProxyFactory.java

/**
 * Cglib子类代理工厂
 * 对UserDao在内存中动态构建一个子类对象
 */public class ProxyFactory implements MethodInterceptor{    //维护目标对象
    private Object target;    public ProxyFactory(Object target) {        this.target = target;
    }    //给目标对象创建一个代理对象
    public Object getProxyInstance(){        //1.工具类
        Enhancer en = new Enhancer();        //2.设置父类
        en.setSuperclass(target.getClass());        //3.设置回调函数
        en.setCallback(this);        //4.创建子类(代理对象)
        return en.create();

    }    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("开始事务...");        //执行目标对象的方法
        Object returnValue = method.invoke(target, args);

        System.out.println("提交事务...");        return returnValue;
    }
}

测试类:

/**
 * 测试类
 */public class App {    @Test
    public void test(){        //目标对象
        UserDao target = new UserDao();        //代理对象
        UserDao proxy = (UserDao)new ProxyFactory(target).getProxyInstance();        //执行代理对象的方法
        proxy.save();
    }
}

在Spring的AOP编程中:
如果加入容器的目标对象有实现接口,用JDK代理
如果目标对象没有实现接口,用Cglib代理

相关推荐:java入门教程

Das obige ist der detaillierte Inhalt vonWas sind die drei Proxy-Modi von Java?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:cnblogs.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen