99 lines
5.0 KiB
Java
99 lines
5.0 KiB
Java
package com.inmind.proxy01;
|
||
|
||
import java.lang.reflect.InvocationHandler;
|
||
import java.lang.reflect.Method;
|
||
import java.lang.reflect.Proxy;
|
||
import java.util.Arrays;
|
||
|
||
/*
|
||
静态代理:直接定义一个固定的类,增强某个类的功能(JingJiRen)
|
||
动态代理:不用定义一个固定的类,动态地增强某个类的功能
|
||
|
||
需求:蔡徐坤的类不能改变,也不能定义经纪人类,但是还想对蔡徐坤的唱跳功能,增强金额判断
|
||
此时只能使用动态代理.
|
||
|
||
--------------------------------------------------------------------------
|
||
总结:
|
||
装饰设计模式(静态代理):
|
||
装饰者 被装饰者 作用:装饰者增强了被装饰者的功能
|
||
花瓶 花 花瓶增强了花的好看的程度
|
||
经纪人(JingJiRen) 歌手(CaiXuKun) 经纪人增强了蔡徐坤的经济价值
|
||
|
||
装饰设计模式的前提: 装饰者需要与被装饰者的功能要一致,继承同一个父类或者实现同一个接口
|
||
BufferedReader FileReader 字符缓冲输入流增加了一个8192数组增强了字符输入流的读取的效率
|
||
--------------------------------------------------------------------------------------------------------------
|
||
动态代理
|
||
代理者 被代理者 作用:代理者能拦截被代理者的指定的功能,进行业务操作
|
||
singerProxy 蔡徐坤 拦截了caiXuKun的sing,dance方法,增加了金额的判断功能
|
||
动态代理的前提条件:代理者与被代理者必须拥有相同的功能,实现同一个接口
|
||
|
||
静态代理与动态代理的区别:
|
||
1.装饰设计模式:注重功能的增强,拥有更多的功能代码,它必须实现所有的抽象方法
|
||
2.动态代理:注重功能方法的拦截,它只需要针对想拦截的方法即可
|
||
*/
|
||
public class Demo03 {
|
||
public static void main(String[] args) {
|
||
//创建出被代理的类-蔡徐坤
|
||
CaiXuKun caiXuKun = new CaiXuKun();
|
||
|
||
|
||
//动态代理参数一:类加载器
|
||
ClassLoader classLoader = caiXuKun.getClass().getClassLoader();
|
||
//动态代理参数二:代理对象要与被代理对象拥有相同的功能,(实现同一套接口)
|
||
Class<?>[] interfaces = caiXuKun.getClass().getInterfaces();
|
||
//动态代理参数三:处理器对象,用来处理代理对象的业务逻辑
|
||
InvocationHandler handler = new InvocationHandler() {
|
||
/*
|
||
注意:动态代理对象singerProxy调用任意方法功能,都会引起处理器的invoke方法来执行
|
||
|
||
invoke方法的三个参数:
|
||
参数一proxy:动态代理对象singerProxy(不要在invoke方法中使用,它引起递归,导致栈内存溢出错误)
|
||
参数二method:反射中Method类,就是当前动态代理调用的方法sing,dance...
|
||
参数三args:当前动态代理调用的方法传入的实参
|
||
*/
|
||
@Override
|
||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||
/*
|
||
业务需求:将经纪人的功能,设置在此
|
||
1.如果是sing,那么要100万才让蔡徐坤唱
|
||
2.如果是dance,那么要120万才让蔡徐坤跳
|
||
*/
|
||
if ("sing".equals(method.getName())) {
|
||
//获取sing方法的实参
|
||
int money = (int) args[0];
|
||
if (money > 100) {
|
||
// caiXuKun.sing(money);
|
||
return method.invoke(caiXuKun,args);
|
||
} else {
|
||
System.out.println("钱不够,一边玩去");
|
||
return null;
|
||
}
|
||
}
|
||
|
||
if ("dance".equals(method.getName())) {
|
||
//获取dance方法的实参
|
||
int money = (int) args[0];
|
||
if (money > 120) {
|
||
// caiXuKun.dance(money);
|
||
return method.invoke(caiXuKun,args);
|
||
}else {
|
||
System.out.println("钱不够,一边玩去");
|
||
return null;
|
||
}
|
||
}
|
||
|
||
//注意:我们此时针对sing,dance进行拦截,但是其他的方法功能还要保留,不要拦截,那就是执行原本的功能
|
||
return method.invoke(caiXuKun,args);//执行蔡徐坤原本的功能
|
||
}
|
||
};
|
||
|
||
//动态地创建出一个代理对象(类似一个经纪人)
|
||
Singer singerProxy = (Singer) Proxy.newProxyInstance(classLoader, interfaces, handler);//多态
|
||
// System.out.println(singerProxy);//toString
|
||
// singerProxy.sing(50);
|
||
singerProxy.dance(150);
|
||
// singerProxy.eat();
|
||
// singerProxy.toString();
|
||
}
|
||
}
|