需要掌握的程度:
1. 什么是JDK动态代理 ?
使用jdk的反射机制,创建对象的能力(创建的是代理类的对象),而不用创建类文件,不用写java文件。
- 动态:在程序执行时,调用jdk提供的方法才能创建代理类的对象。
- jdk动态代理,必须有接口,目标类必须实现接口, 没有接口时,需要使用cglib动态代理。
2. 知道动态代理能做什么?
可以在不改变原来目标方法功能的前提下, 可以在代理中增强自己的功能代码。
代理模式:
1.代理:代购, 中介,换ip,商家等等。
- 比如有一家美国的大学, 可以对全世界招生。
- 留学中介(代理): 帮助这家美国的学校招生, 中介是学校的代理, 中介是代替学校完成招生功能。
为什么要找中介 ?
- 中介是专业的, 方便。
- 家长现在不能自己去找学校。 家长没有能力访问学校。 或者美国学校不接收个人来访。
买东西都是商家卖, 商家是某个商品的代理, 你个人买东西, 肯定不会让你接触到厂家的。
2. 在开发中也会有这样的情况:
- a类, 本来要调用c类的方法, 完成某个功能,但是c不让a调用。
解决方案:
- 在 a 和 c 直接 创建一个 b 代理, c 让 b访问。
a --- 访问b --- 访问c
3.使用代理模式的作用
- 功能增强: 在你原有的功能上,增加了额外的功能。
- 控制访问: 代理类不让你访问目标,例如商家不让用户访问厂家。
静态代理 :
- 代理类是自己手动实现的,自己创建一个java类,表示代理类;同时你所要代理的目标类是确定的。
优点: 实现简单;容易理解。
缺点:当你的项目中,目标类和代理类很多的时候:
1)当目标类增加了, 代理类可能也需要成倍的增加,代理类数量过多。
2)当你的接口中功能增加了, 或者修改了,会影响众多的实现类,厂家类,代理类都需要修改,影响比较多。
动态代理:
- 在程序执行过程中,使用jdk的反射机制,创建代理类对象, 并动态的指定要代理目标类;换句话说: 动态代理是一种创建java对象的能力,让你不用创建代理类,就能创建代理类对象。
优点:
1)代理类数量可以很少。
2)当你修改了接口中的方法时,不会影响代理类。
动态代理的实现:
- jdk 动态代理(理解):使用 java 反射包中的类和接口(InvocationHandler , Method, Proxy)实现动态代理的功能。
- cglib动态代理(了解): cglib是第三方的工具库,cglib的原理是继承, cglib通过继承目标类,创建它的子类,在子类中重写父类中同名的方法, 实现功能的修改。
由于cglib是继承,重写方法,所以要求目标类不能是final的, 方法也不能是final的。
cglib的要求目标类比较宽松, 只要能继承就可以了。cglib在很多的框架中使用,比如 mybatis ,spring框架中都有使用。
jdk 动态代理实现步骤:
1、创建接口,定义目标类要完成的功能:
//目标接口
public interface UsbSell {
float sell(int amount);
}
2、创建目标类实现接口:
//目标类
public class UsbKingFactory implements UsbSell {
@Override
//目标方法
public float sell(int amount) {
//厂家卖85.6元
return 85.6f;
}
}
3、创建InvocationHandler接口的实现类,在invoke方法中完成代理类的功能:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
//必须实现InvocationHandler接口,完成代理类要做的功能(1.调用目标方法,2.功能增强)
public class MySellHandler implements InvocationHandler {
private Object target = null;
//动态代理:目标对象是活动的,不是固定的,需要传入进来,传入是谁,就给谁创建代理。
public MySellHandler(Object target) {
//给目标对象赋值
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//储存方法执行结果
Object res = null;
//执行目标方法
res = method.invoke(target,args);
//商家需要加价(功能增强)
if( res != null ){
Float price = (Float)res;
price = price + 25;
res = price;
}
//再送你一张优惠券(功能增强)
System.out.println(\"谢谢惠顾,送您一张优惠券,亲!\");
//增加的价格
return res;
}
}
4、使用Proxy类的静态方法,创建代理对象。 并把返回值转为接口类型:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class MainShop {
public static void main(String[] args) {
//1. 创建目标对象
UsbSell factory = new UsbKingFactory();
//2.创建InvocationHandler对象
InvocationHandler handler = new MySellHandler(factory);
//3.创建代理对象
UsbSell proxy = (UsbSell) Proxy.newProxyInstance(factory.getClass().getClassLoader(),
factory.getClass().getInterfaces(),
handler);
//4.通过代理执行方法
float price = proxy.sell(1);
System.out.println(\"通过动态代理对象,调用方法获得的结果:\"+price);
}
}
JDK动态代理执行流程 :
来源:https://www.cnblogs.com/Burning-youth/p/16165448.html
本站部分图文来源于网络,如有侵权请联系删除。