java代理模式介绍
我们先来介绍下什么是代理。
(学习视频分享:java视频教程)
代理是一种设计模式,它的核心思想,是将对目标的访问转移到代理对象上。这样做的好处就是,目标对象在不改变代码的情况下,可以通过代理对象加一些额外的功能。这是一种编程思想,在不改变原有代码的情况下,通过代理增加一些扩展功能。
代理过程如图所示,用户访问代理对象,代理对象通过访问目标对象,来达到用户访问目标对象的目的,
代理模式包含一下三个角色:
ISubject:接口对象,该接口是对象和它的代理共用的接口。
TargetSubject:目标对象,是实现抽象主题接口的类。
Proxy:代理角色,内部含有对目标对象TargetSubject的引用,从而可以操作真实对象。代理对象提供与目标对象相同的接口,以便在任何时刻都能代替目标对象。同时,代理对象可以在执行目标对象操作时,附加其他的操作,相当于对真实对象进行封装。
常见的代理模式分为静态代理和动态代理,动态代理在Java中的实现分为JDK动态代理和cglib代理。
静态代理
在之前已经说过,在代理模式中有三个角色,一是目标接口,二是目标对象,三是代理对象。
现在以具体代码来实现,首先是目标接口如下:
public interface IBlogService { void writeBlog(); }
目标对象实现了目标接口,代码如下:
public class BlogService implements IBlogService { @Override public void writeBlog() { System.out.println("i'm writing..."); } }
静态代理对象,通过构造方法获取到目标对象,并实现了目标接口,在目标接口的方法里调用了目标对象的方法,代码如下:
public class BlogStaticProxy implements IBlogService{ private IBlogService blogService; public BlogStaticProxy(IBlogService blogService) { this.blogService = blogService; } @Override public void writeBlog() { System.out.println("start writing..."); blogService.writeBlog(); System.out.println("end writing..."); } }
静态代理对象,通过构造方法获取到目标对象,并实现了目标接口,在目标接口的方法里调用了目标对象的方法,代码如下:
public class BlogStaticProxy implements IBlogService{ private IBlogService blogService; public BlogStaticProxy(IBlogService blogService) { this.blogService = blogService; } @Override public void writeBlog() { System.out.println("start writing..."); blogService.writeBlog(); System.out.println("end writing..."); } }
测试:
public class TestStaticProxy { public static void main(String[] args) { IBlogService target = new BlogService(); BlogStaticProxy proxy = new BlogStaticProxy(target); proxy.write(); } }
start writing… i’m writing… end writing…
静态代理,在不修改目标对象的情况下,可以通过代理对象做额外的扩展功能。但静态方法不是很灵活,如果目标接口的代码修改,目标对象和代理对象都需要修改。
动态代理在一定程度上避免这种情况,动态代理不需要代理对象实现目标接口,并且上在java 虚拟机的内存中动态的生成代理对象
Jdk动态对象
Jdk的动态代理由Proxy这个类来生成,它有三个参数:
ClassLoader loader,:指定当前目标对象使用类加载器,获取加载器的方法是固定的
Class>[] interfaces,:目标对象实现的接口的类型,使用泛型方式确认类型
InvocationHandler h:事件处理,执行目标对象的方法时,会触发事件处理器的方法,会把当前执行目标对象的方法作为参数传入
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException { }
Jdk的动态代理代码如下:
public class JdkBlogProxyFactory { private Object target; public JdkBlogProxyFactory(Object target) { this.target = target; } public Object newInstance() { return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), (proxy, method, args) -> { System.out.println("start writing"); Object o = method.invoke(target, args); System.out.println("end writing"); return o; }); } }
测试类:
public class TestJdkProxy { public static void main(String[] args) { IBlogService target = new BlogService(); System.out.println(target.getClass()); // 给目标对象,创建代理对象 IBlogService proxy = (IBlogService) new JdkBlogProxyFactory(target).newInstance(); // class $Proxy0 内存中动态生成的代理对象 System.out.println(proxy.getClass()); // 执行方法 【代理对象】 proxy.writeBlog(); } }
控制台打印如下:
class com.forezp.proxy.BlogService class com.sun.proxy.$Proxy0 start writing i'm writing... end writing
CGLib动态代理
CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。
CglibBlogFactory代理工厂类如下:
public class CglibBlogFactory implements MethodInterceptor { private Object target; public CglibBlogFactory(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 o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("start writing..."); //执行目标对象的方法 Object returnValue = method.invoke(target, objects); System.out.println("end writing..."); return returnValue; } }
测试类:
public class TestCglib { public static void main(String[] args) { IBlogService target = new BlogService(); //代理对象 IBlogService proxy = (IBlogService) new CglibBlogFactory(target).getProxyInstance(); //执行代理对象的方法 proxy.writeBlog(); } }
运行程序,控制台打印:
start writing... i'm writing... end writing...
相关推荐:java入门教程
Atas ialah kandungan terperinci java代理模式介绍. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas



Panduan Nombor Sempurna di Jawa. Di sini kita membincangkan Definisi, Bagaimana untuk menyemak nombor Perfect dalam Java?, contoh dengan pelaksanaan kod.

Panduan untuk Weka di Jawa. Di sini kita membincangkan Pengenalan, cara menggunakan weka java, jenis platform, dan kelebihan dengan contoh.

Panduan untuk Nombor Smith di Jawa. Di sini kita membincangkan Definisi, Bagaimana untuk menyemak nombor smith di Jawa? contoh dengan pelaksanaan kod.

Dalam artikel ini, kami telah menyimpan Soalan Temuduga Spring Java yang paling banyak ditanya dengan jawapan terperinci mereka. Supaya anda boleh memecahkan temuduga.

Java 8 memperkenalkan API Stream, menyediakan cara yang kuat dan ekspresif untuk memproses koleksi data. Walau bagaimanapun, soalan biasa apabila menggunakan aliran adalah: bagaimana untuk memecahkan atau kembali dari operasi foreach? Gelung tradisional membolehkan gangguan awal atau pulangan, tetapi kaedah Foreach Stream tidak menyokong secara langsung kaedah ini. Artikel ini akan menerangkan sebab -sebab dan meneroka kaedah alternatif untuk melaksanakan penamatan pramatang dalam sistem pemprosesan aliran. Bacaan Lanjut: Penambahbaikan API Java Stream Memahami aliran aliran Kaedah Foreach adalah operasi terminal yang melakukan satu operasi pada setiap elemen dalam aliran. Niat reka bentuknya adalah

Panduan untuk TimeStamp to Date di Java. Di sini kita juga membincangkan pengenalan dan cara menukar cap waktu kepada tarikh dalam java bersama-sama dengan contoh.

Kapsul adalah angka geometri tiga dimensi, terdiri daripada silinder dan hemisfera di kedua-dua hujungnya. Jumlah kapsul boleh dikira dengan menambahkan isipadu silinder dan jumlah hemisfera di kedua -dua hujungnya. Tutorial ini akan membincangkan cara mengira jumlah kapsul yang diberikan dalam Java menggunakan kaedah yang berbeza. Formula volum kapsul Formula untuk jumlah kapsul adalah seperti berikut: Kelantangan kapsul = isipadu isipadu silinder Dua jumlah hemisfera dalam, R: Radius hemisfera. H: Ketinggian silinder (tidak termasuk hemisfera). Contoh 1 masukkan Jejari = 5 unit Ketinggian = 10 unit Output Jilid = 1570.8 Unit padu menjelaskan Kirakan kelantangan menggunakan formula: Kelantangan = π × r2 × h (4

Spring Boot memudahkan penciptaan aplikasi Java yang mantap, berskala, dan siap pengeluaran, merevolusi pembangunan Java. Pendekatan "Konvensyen Lebih Konfigurasi", yang wujud pada ekosistem musim bunga, meminimumkan persediaan manual, Allo
