代理
什么是代理模式
代理模式是程序设计中的一种常见设计模式。代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用,代理对象主要负责为委托对象(真实对象)预处理消息、过滤消息、传递消息给委托类,代理类不现实具体服务,而是利用委托类来完成服务,并将执行结果封装处理。
为什么要用代理
中介隔离:在某些情况下,一个客户类不想或者不能直接引用一个委托对象,而代理类对象可以在客户类和委托对象之间起到中介的作用,其特征是代理类和委托类实现相同的接口。
开闭原则,增加功能:代理类除了是客户类和委托类的中介之外,我们还可以通过给代理类增加额外的功能来扩展委托类的功能,这样做我们只需要修改代理类而不需要再修改委托类,符合代码设计的开闭原则。代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后对返回结果的处理等。代理类本身并不真正实现服务,而是同过调用委托类的相关方法,来提供特定的服务。真正的业务功能还是由委托类来实现,但是可以在业务功能执行的前后加入一些公共的服务。例如我们想给项目加入缓存、日志这些功能,我们就可以使用代理类来完成,而没必要打开已经封装好的委托类。
动态代理
在程序执行中,使用jdk的反射机制,创建代理类对象,并动态的指定要代理的目标类。动态代理是一种创建Java对象的能力,不用创建类就能创建代理类对象
动态代理类型
动态代理分为JDK动态代理和cglib动态代理两类
-
JDK动态代理: 使用Java反射包
java.lang.reflect
和接口实现动态代理的功能,包下有三个主要类:-
InvocationHandler接口
-
InvocationHandler
是由代理实例的调用处理程序实现的接口 。 -
每个代理实例都有一个关联的调用处理程序。
-
当在代理实例上调用方法时,方法调用将被编码并分派到其调用处理程序的invoke方法。
-
InvocationHandler
接口只有一个方法invoke()
-
invoke():表示代理对象要执行的功能代码。代理类要完成的功能就写在
invoke()
方法中。
-
-
Method类
- 表示目标类中的方法
- 通过
Method. invoke()
可以执行某个目标类的方法, method. invoke(目标对象,方法的参数)
-
Proxy类
- 核心的对象,通过静态方法
newProxyInstance()
创建代理对象,等同于静态代理中的A a = new A()
- 核心的对象,通过静态方法
-
-
cglib动态代理:cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。cglib是通过继承目标类来实现的,故要求目标类及其方法不能为final修饰。cglib应用于多种框架,如mybatis,spring等
Java动态代理步骤
-
创建接口,定义目标类要完成的功能
-
创建目标类实现接口
-
创建InvocationHandler接口的实现类,在invoke方法中完成代理类的功能
-
调用目标方法
-
增强功能
-
使用Proxy类的静态方法,创建代理对象,并把返回值转换成接口类型
Java动态代理样例
- 创建接口,定义目标类要完成的功能
public interface ProductSell {
int getPrice(int price);
}
- 创建目标类实现接口
public class ProductSellImpl implements ProductSell {
@Override
public int getPrice(int price) {
System.out.println("商品原价:"+price);
return price;
}
}
- 创建InvocationHandler接口的实现类,在invoke方法中完成代理类的功能
public class MySellHandler implements InvocationHandler {
private Object target;
public MySellHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object res ;
res = method.invoke(target,args);
System.out.println("开始动态代理,商品价格+15");
return (int)res+15;
}
}
- 使用Proxy类的静态方法,创建代理对象,并把返回值转换成接口类型
public class MainShop {
public static void main(String[] args) {
//创建代理对象,使用Proxy
// 1.创建目标对象
ProductSell productSell = new ProductSellImpl();
//2.创建InvocationHandler对象
MySellHandler mySellHandler = new MySellHandler(productSell);
//3.创建代理对象
ProductSell proxyInstance = (ProductSell) Proxy.newProxyInstance(mySellHandler.getClass().getClassLoader(), productSell.getClass().getInterfaces(), mySellHandler);
int price = proxyInstance.getPrice(12);
System.out.println("通过动态代理创建对象:最终价格"+price);
}
}
- 执行代理,查看结果