个人网站如何做移动端,三亚网红餐厅,wordpress wp roket,wordpress 插件库动态代理 知道什么是动态代理以及动态代理能干什么就可以 代理的概述
什么是动态代理
使用jdk的反射机制#xff0c;创建对象的能力#xff0c; 创建的是代理类的对象。
动态#xff1a;在程序执行时#xff0c;调用jdk提供的方法才能创建代理类的对象。jdk动态代理创建对象的能力 创建的是代理类的对象。
动态在程序执行时调用jdk提供的方法才能创建代理类的对象。jdk动态代理必须有接口目标类必须实现接口 没有接口时需要使用cglib动态代理
动态代理能做什么
可以在不改变原来目标方法功能的前提下 可以在代理中增强自己的功能代码。
例如实际开发中你所在的项目中有一个功能是其他人公司的其它部门其它小组的人写好的你可以使用。你发现这个功能现在还缺点不能完全满足我项目的需要。 我需要在gn.print()执行后需要自己在增加代码。用代理实现 gn.print调用时 增加自己代码 而不用去改原来的 GoNong文件。
// GoNong.class
GoNong gn new GoNong();
gn.print(); 注意不知道源代码不能使用重写而且你要用写好的功能想要去扩展功能就只能先把写好的方法执行一边然后再代理中扩展重写的话原来写好的方法也没了
什么是代理
生活中的代理
代理就是中介、代购、商家等。
例如留学中介就是一个代理我想上美国的一所大学但是我没办法去这个大学实地考察也没办法要这个大学的联系方式并且这个大学拒绝个人去访问它。但是这个大学在国内把招生业务委派给了一个留学中介。这样我就可以去和留学中介交谈留学中介可以与美国大学联系。留学中介会从我这里收取额外的中介费。
在以上的案例中学校是目标留学中介是代理我是客户。它们具有以下特点 中介和代理他们要做的事情是一致的 招生。 中介是学校代理 学校是目标。 我—中介学校介绍办入学手续----美国学校。 中介是代理不能白干活需要收取费用。 代理不让你访问到目标。
为什么要找中介 中介是专业的方便 我现在不能自己去找学校。 我没有能力访问学校。 或者美国学校不接收个人来访。 买东西都是商家卖 商家是某个商品的代理 你个人买东西 肯定不会让你接触到厂家的。
开发中的代理模式代理
代理模式是指当一个对象目标无法直接使用时可以在该客户端和目标类之间创建一个中介这个中介就是代理。
在实际开发中有这样情况有一个A类有一个C类但是C类不允许A类直接访问这样我们可以创建一个A类和C类之间的B类C类允许B类访问这样我们可以在A类中访问B类然后B类在访问C类这样就相当于在A类中间接访问到了C类。其中A类是客户类B类是代理类C类是目标类。另外我可以在B类中添加一些内容意味着功能增强。
使用代理模式的作用
功能增强 在你原有的功能上增加了额外的功能。 新增加的功能叫做功能增强。 (例如留学中介要收取额外的费用)控制访问 代理类不让你访问目标例如商家不让用户访问厂家。就跟房屋中介肯定不会给房东电话给你否则它们怎么赚中介费
实现代理的方式 实现代理的方式有静态代理动态代理 静态代理
什么是静态代理
静态代理代理类是手工创建的代理的目标类是固定的。
静态代理的实现步骤 模拟一个用户购买u盘的行为其中用户是客户端类商家是代理类厂家是目标类商家和厂家都是卖U盘的应该把卖U盘这个动作抽象为一个接口。 创建一个接口定义卖u盘的方法 表示你的厂家和商家做的事情。 // 表示功能的厂家商家都要完成的功能
public interface UsbSell {//定义方法 参数 amount:表示一次购买的数量暂时不用//返回值表示一个u盘的价格。float sell(int amount);//可以多个其它的方法//void print();
}创建厂家类实现1步骤的接口 //目标类金士顿厂家, 不接受用户的单独购买。
public class UsbKingFactory implements UsbSell {Overridepublic float sell(int amount) {System.out.println(目标类中的方法调用 , UsbKingFactory 中的sell );//一个128G的u盘是 85元。//后期根据amount 可以实现不同的价格例如10000个单击是80 50000个75return 85.0f;}
} 创建商家就是代理类也需要实现1步骤中的接口。 // taobao是一个商家代理金士顿u盘的销售。
public class TaoBao implements UsbSell {// 声明 商家代理的厂家具体是谁// private修饰为了控制访问不让客户知道厂家是谁private UsbKingFactory factory new UsbKingFactory();Override// 实现销售u盘功能public float sell(int amount) {// 向厂家发送订单告诉厂家我买了u盘厂家发货float price factory.sell(amount); //厂家的价格。// 商家 需要加价 也就是代理要增加价格。price price 25; //增强功能代理类在完成目标类方法调用后增强了功能。// 在目标类的方法调用后你做的其它功能都是增强的意思。System.out.println(淘宝商家给你返一个优惠券或者红包);// 增加的价格return price;}
}public class WeiShang implements UsbSell {//代理的是 金士顿定义目标厂家类private UsbKingFactory factory new UsbKingFactory();Overridepublic float sell(int amount) {//调用目标方法float price factory.sell(amount);//只增加1元price price 1;return price;}
}创建客户端类调用商家的方法买一个u盘。 public class Customer {public static void main(String[] args) {// 通过淘宝卖// 下载了淘宝的app/*TaoBao taoBao new TaoBao();// 通过代理类实现购买u盘增加了优惠券红包等等float price taoBao.sell(1);System.out.println(淘宝的价格 price);*/// 取得微商的联系方式WeiShang weiShang new WeiShang();// 通过微商代理实现购买u盘增加了优惠券红包等等float price weiShang.sell(1);System.out.println(通过微商购买的价格 price);}
}分析问题
以上实例若只有一个目标类如金士顿厂家商家只需要和这个厂家联系就行。但是如果又有一个闪迪厂家那么得重写一套代理类因为一个代理类中只能指定一个厂家如以上的淘宝类制定了厂家是金士顿就不能在指定闪迪厂家只能重新新建一个代理类在这个代理类中指定厂家是闪迪微商也是一样要来一个专门代理闪迪的微商。如果有100个厂家那么就要写200个代理类。如果UsbSell接口多了个退货功能那么所有的目标类和代理类都要修改。
静态代理的优缺点
优点 实现简单容易理解 缺点当你的项目中目标类和代理类很多时候有以下的缺点 当目标类增加了代理类可能也需要成倍的增加。 代理类数量过多。当你的接口中功能增加了或者修改了会影响众多的实现类厂家类代理都需要修改。影响比较多。
简而言之静态代理容易理解代码好写但是各个类之间耦合度太高一旦扩展就有问题
动态代理重点
什么是动态代理
动态代理就是在程序执行过程动态中使用jdk的反射机制创建代理类对象 并动态的指定要代理目标类。换句话说 动态代理是一种创建java对象的能力让你不用自己写代理类的java程序然后new对象。而是直接用jdk创建代理类对象。这样我不关心代理类是谁我只知道它能增强功能并且通过它我可以找到目标类。类似暗下交易
动态代理的优点
优点 动态代理中目标类即使很多但是代理类数量可以很少当你修改了接口中的方法时不会影响代理类压根就不用写代理类了这个代理类是jdk创建的只是起到一个中介的功能。符合OCP原则不用创建代理类文件代理的目标类是灵活的可以随意给不同目标创建代理
动态代理的两种实现方式
jdk动态代理理解 使用java反射包中的类和接口实现动态代理的功能。 反射包 java.lang.reflect , 里面有三个类 InvocationHandler , Method, Proxy. cglib动态代理了解: cglib是第三方的工具库 创建代理对象。 cglib的原理是继承 cglib通过继承目标类创建它的子类在子类中重写父类中同名的方法 实现功能的修改。因为cglib是继承重写方法所以要求目标类不能是final的 方法也不能是final的。cglib的要求目标类比较宽松 只要能继承就可以了。cglib在很多的框架中使用比如 mybatis spring框架中都有使用。
注意jdk动态代理必须有接口对于无接口类必须使用cglib来为它创建动态代理
jdk动态代理的实现 需要用到反射包 java.lang.reflect里面有三个类 InvocationHandler , Method, Proxy. InvocationHandler 接口调用处理器
该接口中只有一个方法invoke()方法invoke()方法最后是由代理类调用的所以代理类完成的功能写在该方法里 代理类完成的功能调用目标方法、功能增强
public Object invoke(Object proxy, Method method, Object[] args)invoke方法参数
proxy代理对象由jdk创建method目标方法因为代理类的功能是调用目标方法所以这里要给出args目标方法的参数
如何理解InvocationHandler接口 InvocationHandler接口表示你的代理想要干什么即代理完成的功能写在该接口实现类的invoke方法中 使用方法 创建类实现接口InvocationHandler重写invoke()方法把原来静态代理中代理类要完成的功能写在这。
Method类
method表示目标类中的方法method是要发给InvocationHandler实现类的invoke方法的参数表示代理所调用的目标方法
Proxy类
通过该类可以生成代理对象代理对象的创建是由jdk提供的我们只是负责调Proxy类中的方法来拿到这个代理对象调用Proxy类中的静态方法newProxyInstance()可以创建一个代理对象具体创建步骤是由jdk完成的
public static Object newProxyInstance(ClassLoader loader,Class?[] interfaces,InvocationHandler h)newProxyInstance参数说明
loader表示目标对象的类加载器固定写法目标对象.getClass().getClassLoader();interfaces表示目标对象所实现的接口接口多继承因此是个数组。固定写法目标对象.getClass().getInterface();h表示代理类所要完成的功能
返回值就是代理类对象并且在该对象创建时已经说明了该代理类对象所代理的目标对象是谁该目标对象完成了那些功能该代理类所要完成的功能
动态代理的实现步骤 创建接口定义目标类要完成的功能 /*** 目标类要完成的功能*/
public interface UsbSell {float sell(int amount);
}创建目标类实现接口 //目标类金士顿厂家, 不接受用户的单独购买。
public class UsbKingFactory implements UsbSell {Overridepublic float sell(int amount) {System.out.println(目标类中的方法调用 , UsbKingFactory 中的sell );//一个128G的u盘是 85元。//后期根据amount 可以实现不同的价格例如10000个单击是80 50000个75return 85.0f;}
}创建InvocationHandler接口的实现类在invoke方法中完成代理类的功能 1.调用目标方法 2.增强功能 //必须实现InvocationHandler接口完成代理类要做的功能1.调用目标方法2.功能增强
public class MySellHandler implements InvocationHandler {private Object target null;//动态代理目标对象是活动的不是固定的需要传入进来。//传入是谁就给谁创建代理。public MySellHandler(Object target) {//给目标对象赋值this.target target;}Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object res null;//向厂家发送订单告诉厂家我买了u盘厂家发货//float price factory.sell(amount); //厂家的价格。res method.invoke(target,args); //执行目标方法//商家 需要加价 也就是代理要增加价格。//price price 25; //增强功能代理类在完成目标类方法调用后增强了功能。if( res ! null ){Float price (Float)res;price price 25;res price;}//在目标类的方法调用后你做的其它功能都是增强的意思。System.out.println(淘宝商家给你返一个优惠券或者红包);//记录数据库//增加的价格return res;}
}使用Proxy类的静态方法创建代理对象。 并把返回值转为接口类型。 public class Customer {public static void main(String[] args) {//创建代理对象使用Proxy//1. 创建目标对象// UsbKingFacotry factory new UsbKingFactory();UsbSell factory new UsbKingFactory();//2.创建InvocationHandler对象InvocationHandler handler new MySellHandler(factory);//3.创建代理对象UsbSell proxy (UsbSell) Proxy.newProxyInstance(factory.getClass().getClassLoader(),factory.getClass().getInterfaces(),handler);//com.sun.proxy.$Proxy0 : 这是jdk动态代理创建的对象类型。System.out.println(proxy:proxy.getClass().getName());//4.通过代理执行方法float price proxy.sell(1);System.out.println(通过动态代理对象调用方法price);}
}动态代理开发中实例
// 目标完成的功能
public interface HelloService {//打印报告 报表int print(String name);
}// 目标类
public class GoNeng implements HelloService {Overridepublic int print(String name) {System.out.println(其它人写好的个功能方法);return 2;}
}// 代理完成的功能
public class MyInvocationHandler implements InvocationHandler {private Object target null;public MyInvocationHandler(Object target) {this.target target;}Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//我在项目中记录数据库//调用目标方法 执行print()得到 2Object res method.invoke(target,args); //2// 代理进行“功能增强”//需要乘以 2的结果 if( res ! null){Integer num (Integer)res;res num * 2;}return res;}
}// 测试类
public class MyApp {public static void main(String[] args) {// GoNeng gn new GoNeng();//int num gn.print(销售);// System.out.println(numnum);// 创建目标类GoNeng goNeng new GoNeng();// 代理完成的功能InvocationHandler handler new MyInvocationHandler(goNeng);// 这里表示目标类必须实现一个接口否则不能用jdk实现动态代理只能用cglib实现动态代理System.out.println(goNeng.getClass().getInterfaces()goNeng.getClass().getInterfaces()[0].getName());HelloService proxy (HelloService) Proxy.newProxyInstance( goNeng.getClass().getClassLoader(),goNeng.getClass().getInterfaces(),handler);// 代理proxy的print方法实际上是接口中的因为再创建代理是把目标类的构造器和实现的接口都给了代理并且代理完成的功能也给了代理// 代理执行print方法就去handler的invoke方法把print方法给了method参数“市场”给了argsint num proxy.print(市场);System.out.println(我们期望的 num num);// 总之proxyhandler目标类之间是相关联的。}
}