使用代理的好处:功能增强,控制访问
1.静态代理
代理类是自己手工实现,自己创建一个java类,表示代理类,同时所要代理的目标对象是确定的
特点:实现简单,容易理解
缺点:当目标类增加了,代理类也需要成倍的增加(类爆炸),当接口功能增加了会影响众多的实现类
举例:
定义方法--创建一个接口 UsbSell 定义一个sell方法
package com.example.demo.proxy.staticproxy;
/**
* @author hanzl
* @date 2021/1/31 8:44 下午
* 接口
*/
public interface UsbSell {
//定义方法
public int sell(int count);
}
创建目标类 UsbFactory 实现 UsbSell 接口
package com.example.demo.proxy.staticproxy;
/**
* @author hanzl
* @date 2021/1/31 8:44 下午
* 目标类
*/
public class UsbFactory implements UsbSell {
@Override
public int sell (int count) {
return 80;
}
}
创建代理类 Taobao 实现 UsbSell 接口 目的是扩展目标类的功能
package com.example.demo.proxy.staticproxy;
/**
* @author hanzl
* @date 2021/1/31 8:45 下午
* 代理类
*/
public class Taobao implements UsbSell {
private UsbFactory usbFactory=new UsbFactory();
@Override
public int sell (int count) {
int res= usbFactory.sell(count);
System.out.println("执行了代理类的方法");
//扩展功能
res+=res+20;
return res;
}
}
测试静态代理
package com.example.demo.proxy.staticproxy;
/**
* @author hanzl
* @date 2021/1/31 8:48 下午
* 测试
*/
public class TestMain {
public static void main(String args[]){
Taobao taobao=new Taobao();
taobao.sell(5);
}
}
2.动态代理
特点:代理类数量可以很少; 当修改接口中的方法时,不会影响代理类; 程序执行过程中,使用jdk代理目标对象是活动的,利用反射机制可以给不同的目标对象创建代理
Jdk动态代理:使用反射包中的类和接口实现, Jdk动态代理必须使用接口 ,反射包中的 invocationhandler,Method, proxy
Cglib动态代理:核心是继承
Jdk动态代理实现的核心:
1.创建接口:定义目标类要完成的功能
package com.example.demo.proxy.dynamic;
/**
* @author hanzl
* @date 2021/1/31 9:19 下午
* 创建接口,定义方法
*/
public interface Singer {
//定义唱歌的方法
public String sing(String s);
}
2.创建目标类实现接口
package com.example.demo.proxy.dynamic;
/**
* @author hanzl
* @date 2021/1/31 9:20 下午
* 目标类,刘德华,实现唱歌的功能
*/
public class Liudehua implements Singer{
@Override
public String sing (String s) {
s="hello,"+s+"给我一杯忘情水";
System.out.println(s);
return s;
}
}
3.创建invocationhandler接口实现类,在invoke方法中完成代理类的功能:即调用目标方法,增强功能
package com.example.demo.proxy.dynamic;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* @author hanzl
* @date 2021/1/31 9:22 下午
* 自定义MyInvocationHandler 实现 InvocationHandler 接口
*/
public class MyInvocationHandler implements InvocationHandler {
private Object target=null;
public MyInvocationHandler(Object target){
this.target=target;
}
@Override
public Object invoke (Object proxy, Method method, Object[] args) throws Throwable {
Object res=method.invoke(target,args);
System.out.println("执行了代理:"+res.toString());
return res;
}
}
4.使用proxy类的静态方法,创建代理对象,调用方法
package com.example.demo.proxy.dynamic;
import java.lang.reflect.Proxy;
/**
* @author hanzl
* @date 2021/1/31 9:26 下午
* 测试动态代理
*/
public class TestMain {
public static void main(String args[]){
//目标对象
Singer target=new Liudehua();
MyInvocationHandler myInvocationHandler=new MyInvocationHandler(target);
Singer singer=(Singer)Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),myInvocationHandler);
singer.sing("hanzl");
}
}
5.执行结果