什么是动态代理?
- 使用JDK的反射机制,创建对象的能力,创建的是代理类的对象,不用程序员自己创建类文件
- 动态:在程序执行时,调用JDK提供的方法才能创建代理类的对象
- 有两种动态代理的方式:
- 1) jdk动态代理,通过反射包中的类和接口实现动态代理
- 2) cglib动态代理,cglib是第三方的工具库,通过继承目标类,创建子类实现动态代理
什么是代理类对象?
假如 :a是用户,c是厂家,一般来说,a如果想购物,是不能直接去厂家买东西的,所以出现了一个代理–淘宝b
a不能直接访问c,但是可以通过b访问c,即:a->b->c
代理对象可以实现目标对象的方法,即b实现了c的方法,且a调用b的方法
且在代理对象实现目标对象的方法时候,可以拥有自己的方法,达到增强功能的作用
比如:b淘宝实现c厂家卖东西的功能------c厂家有卖东西的方法,b淘宝也有卖东西的方法
但是b淘宝除了卖东西之外,还可以写闲置的方法
为什么不用静态代理?
静态代理对象是我们手动创建的,且当代理对象实现了目标对象的方法之后,如果接口需要对方法进行改动,那么所有的实现类都需要进行改动,过于麻烦,所以采用动态代理
知道动态代理能做什么?
可以在不改变原来目标方法功能的前提下,可以在代理中增强自己的功能代码
程序开发中:
- 项目中,有人写好了一个功能,大家可以使用。
- Gongneng .class
- Gongneng gn =new Gongneng ()
- gn.print();
- 你发现这个功能,现在还缺点东西,不能完全满足我自己项目的需要,我需要在gn.print()执行后,需要添加自己的代码。可以用代理实现gn.print(),调用后,增加自己的代码,而不用去改原来的Gonneng文件
jdk动态代理
-
InvocationHandler
接口(调用处理器),里面只有一个方法invoke()这个方法跟反射调用方法没关系这个接口表示:你的代理对象需要干什么?需要实现的功能
public interface InvocationHandler { //var1是jdk创建的代理对象 //var2是目标类中的方法,jdk提供method对象的 //var3是目标类中的方法参数,jdk提供的 Object invoke(Object var1, Method var2, Object[] var3) throws Throwable; }
-
Method
类:表示方法,目标类中的方法作用:通过Method可以执行某个目标类的方法:Method.invoke()–>通过反射机制调用方法,执行目标方法
-
Proxy类:核心的对象,创建代理对象,之前创建对象都是new类的构造方法(),限制是使用Proxy类的方法,代替new的使用
方法:静态方法 newProxyInstance()
public static Object newProxyInstance (ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
参数:
ClassLoader loader
:类加载器,负责向内存中加载对象,使用反射获取对象的类 a,a.getClass.getClassLoder()Class<?>[] interfaces
:接口,目标对象实现的接口,通过反射获取InvocationHandler h
:我们自己写的代理类要完成的功能
返回值就是代理对象
实现动态代理的步骤
- 创建接口,定义目标类要完成的功能
- 创建目标类实现接口
- 创建InvocationHandler接口的实现类,在invoke方法中完成代理类的功能
- 调用目标方法
- 增强功能
- 使用Proxy类的静态方法,创建代理对象,并把返回值转为接口类型
//接口
public interface UsbSell {
float sell(int count);
}
//目标类(厂家)
public class UsbKingFactory implements UsbSell{
@Override
public float sell(int count) {
System.out.println("目标类执行sell目标方法");
return 80f;
}
}
//必须实现InvocationHandler接口,完成代理类要做的功能(1.调用目标方法,2.功能增强)
public class MySellHandler implements InvocationHandler {
private Object target;
//目标对象是活动的,不是固定的,需要传入尽量
//传入的是谁,就给谁创建代理
public MySellHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] argss) throws Throwable {
Object res=null;
//等于:
// UsbSell usbFactory = new UsbKingFactory();
// float price = usbFactory.sell(100);
res = method.invoke(target, args);//执行目标方法
//商家需要加价,也就是代理要增加价格
//price = price +2
if (res!=null) {
Float price = (Float) res;
price = price + 2;
res = price;
}
return res;
}
}
//
public class MainShop {
public static void main(String[] args) {
//1.创建目标对象
UsbSell factory = new UsbKingFactory();
//2.创建InvocationHandler对象
InvocationHandler hander = new MySellHandler(factory);
//3.创建代理对象
UsbSell proxy = (UsbSell)Proxy.newProxyInstance(
factory.getClass().getClassLoader(),factory.getClass().getInterfaces(),hander);
//4.通过代理执行方法
float price = proxy.sell(20);
System.out.println(price);
}
}
具体案例实现
public interface HelloService {
int print();
}
public class Goneng implements HelloService{
@Override
public int print() {
System.out.println("其他人写好的功能");
return 2;
}
}
//以上部分是其他人写好的功能方法,可以让别人调用的
//实现InvocationHandler接口,完成代理类要做的功能
//此处功能是实现目标类(功能方法),和增强功能(自己的代码自己的需求)
public class MyInvocationHandler implements InvocationHandler {
private Object target;
public MyInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//调用目标方法得到的是2
Integer num = 0;
Object res = method.invoke(target, args);//2
if (res !=null){
num = (Integer) res;
num = num*2;
}
return num;
}
}
public class MyApp {
public static void main(String[] args) {
Goneng goneng = new Goneng();
MyInvocationHandler handler = new MyInvocationHandler(goneng);
HelloService proxy = (HelloService) Proxy.newProxyInstance(goneng.getClass().getClassLoader(), goneng.getClass().getInterfaces(), handler);
int num = proxy.print();
System.out.println("代理后:"+num);//4
}
}