设计模式之代理模式
admin
2024-01-25 07:47:20

代理模式

代理模式有动态代理和静态代理:静态代理模式中代理类是自己已经定理好的,在程序运行前就已经编译好了,然而动态代理,代理类并不是在Java代码中定义的,而是在运行时根据我们在Java代码中的“指示”动态生成的。*相比于静态代理, 动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类中的方法* 比如说,想要在每个代理的方法前都加上一个处理方法:

JDK和CGLIB的区别

JDK动态代理只能对实现了接口的类生成代理,而不能针对类,使用的是Java反射技术实现,不需要第三方库的支持,生成比较高效。

CGLIB主要是针对一个类生成子类,覆盖其中的方法,是一种继承,并且需要第三方库asm字节码框架来支持。

静态代理

1.确定创建接口具体行为

/***  确定具体得行为接口* */
public interface Person {// 上交班费void giveMoney();

2.被代理对象 Student 实现接口,实现接口的具体行为的方法。

/*** 被代理类*/
public class Student implements Person{@Overridepublic void giveMoney() {System.out.println("学生上交班费....");}
}

3.代理对象,因为代理对象需要去代理被代理对象,所以代理对象必须同样实现被代理对象类的接口。代理对象需要完成委托类预处理消息,消息过滤、转发,所以他必须得持有一个被代理对象,可以是继承或者是关联。

/*** 学生的代理类  实现消息的委托、转发*/
public class StudentsProxy implements Person{// 消息的委托必须要交给被代理类,所以得关联一个被代理类private Student student;// 只会代理学生类public StudentsProxy(Person student){if (student.getClass() == Student.class){this.student = (Student) student;}}// 代替上交班费 调用被代理学生得上交班费行为@Overridepublic void giveMoney() {// 代理类增加其他前置逻辑System.out.println("由我给你张三代缴班费吧。。。。。");student.giveMoney();}
}

4.测试

public class ProxyTest {public static void main(String[] args) {// 创建被代理类Student zhangSan = new Student();//  创建代理类并且代理张三上交班费Person studentsProxy  = new StudentsProxy(zhangSan);// 这样上缴班费就交给了学生得代理类了 用户无感知,只知道由谁能够给我实现上交班费功能即可。studentsProxy.giveMoney();}
}

动态代理

1.确定创建接口得具体行为

/***  确定具体得行为接口* */
public interface Person {// 上交班费void giveMoney();
}

2.确定被代理对象实现接口,并且完成具体业务逻辑

/*** 被代理类*/
public class Student implements Person {@Overridepublic void giveMoney() {System.out.println("学生上交班费....");}
}

3.自定义一个InvocationHandler类,并且实现InvocationHandler接口,这个类种会持有一个被代理对象target,并且InvocationHandler中有一个invoke方法,所有执行代理对象得方法都会被替换成执行invoke方法

/*** @Author Tang**/
public class StudentInvocationHandler implements InvocationHandler {// 持有一个被代理对象T target;// 定义一个构造器public StudentInvocationHandler(T target) {this.target = target;}/*** proxy:代表动态代理对象* method 代表正在执行得方法* args:代表调用目标方法时传入的实参*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("执行方法....");method.invoke(target, args);System.out.println("执行结束,结果为:");return "执行成功....";}
}

4.测试

public class ProxyTest {public static void main(String[] args) {// 生成一个被代理类Person student =  new Student();StudentInvocationHandler studentInvocationHandler = new StudentInvocationHandler(student);// 使用Proxy得静态方法创建代理类   // 第一个参数是我们被代理的对象 也可以写成它实现的接口 // 第二个 interface对象数组 表明代理类实现了这些接口 那么代理类就可以调用接口中声明的所有方法。// 第三个 表示的是当动态代理对象调用方法的时候会关联到哪一个InvocationHandler对象上Person personProxy=(Person) Proxy.newProxyInstance(Person.class.getClassLoader(), new Class[]{Person.class}, studentInvocationHandler);//使用动态代理类来personProxy.giveMoney();}
}
public static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)

这个方法的作用就是创建一个代理类对象,它接收三个参数,我们来看下几个参数的含义:

loader:一个classloader对象,定义了由哪个classloader对象对生成的代理类进行加载
interfaces:一个interface对象数组,表示我们将要给我们的代理对象提供一组什么样的接口,如果我们提供了这样一个接口对象数组,那么也就是声明了代理类实现了这些接口,代理类就可以调用接口中声明的所有方法。
h:一个InvocationHandler对象,表示的是当动态代理对象调用方法的时候会关联到哪一个InvocationHandler对象上,并最终由其调用。

相关内容

热门资讯

杭州灵隐飞来峰景区12月1日起...   新华社杭州11月19日电(记者段菁菁)为更好地满足市民游客的旅游需求、提升游览品质,杭州西湖风景...
杭州官宣取消灵隐寺门票! 每经编辑|程鹏 11月19日,每经小编从杭州西湖景区官方账号了解到,自2025年12月1日起,灵隐...
装上伊贝莎泳池,民宿营业额反超... “之前旺季靠降价抢单,现在客人主动加价订周末房!” 经营民宿三年的李姐,至今对引入伊贝莎泳池后的变化...
霉腌醉酱的美食哲学,看中国烹饪... 主讲人、图片提供 / 茅天尧 文字整理 / 孙阳 绍兴菜历史悠久,技艺源远流长,以“霉”“腌”“醉...