代理(proxy)
在编译时期无法确定需要实现哪个接口时才有必要实现代理。
代理类可以在运行时创建全新的类,这样的代理类可以实现指定的接口。
代理类包含的方法:
- 指定接口所需要的全部方法
- Object类的全部方法
代理类的特性
代理类是在程序的运行过程中动态创建的,一旦被创建,它们也就变成了常规类,与虚拟机的常规类没有什么区别。
所有代理类的父类时Proxy类。
代理类总是public和final。
由代理类和被代理类组成,类似于经纪人和明星之间的关系,是否创建对象由代理类进行决定,代理类和被代理类必须实现同一个接口,调用代理类方法实现同名被代理类方法的执行,在运行期间进行创建动态一个总代理类,称为动态代理,通过反射进行。
- 静态代理(代理类和被代理类在编译期间就确定下来了)
interface Factory {
void produce();
}
//代理类
public class ProxyProduce implements Factory{
private Factory factory;//被代理类对象实例化
public ProxyProduce(Factory factory){
this.factory = factory;
}
@Override
public void produce() {
System.out.println("我是代理类,我在做准备!");
factory.produce();
System.out.println("生产完毕Over!");
}
}
//被代理类
public class Apple implements Factory{
@Override
public void produce() {
System.out.println("我生产苹果手机");
}
public static void main(String[] args) {
Apple apple = new Apple();
ProxyProduce proxyProduce = new ProxyProduce(apple);
proxyProduce.produce();
}
}
- 动态代理
只要是代理模式的话必须要有一个接口标准与一个被代理类(真正干活的)
interface Factory {
void produce();
}
public class ProxyFactory {
//通过调用此方法返回一个全局唯一的动态代理类对象obj
public static Object getProxy(Object obj){
ProxyInvocation invocation = new ProxyInvocation();
invocation.bind(obj);
Object instance = Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), invocation);
return instance;
}
}
//解决调用代理类方法时匹配到被代理类的同名方法
public class ProxyInvocation implements InvocationHandler {
private Object object;
public void bind(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object invoke = method.invoke(object, args);
return invoke;
}
}
//被代理类
public class Apple implements Factory {
@Override
public void produce() {
System.out.println("我生产苹果手机");
}
public static void main(String[] args) {
Apple apple = new Apple();
//代理类调用同名方法,传到ProxyInvocation中,声明为接口类型
Factory proxy = (Factory) ProxyFactory.getProxy(apple);
proxy.produce();
}
}