proxyNote - juedaiyuer/researchNote GitHub Wiki
#代理模式#
为其他对象提供一种代理以控制对这个对象的访问
代理对象起中介作用,可去掉功能服务或增加额外的服务
对象消耗太多资源,并不是每一条逻辑路径都需要这个对象,延迟创建对象的想法
限制访问某个对象,提供一组方法给普通用户,特殊方法给管理员用户
远程代理
Remote Proxy
为不同地理的对象,提供局域网代表对象
远程代理又称之为大师(Ambassador)
虚拟代理
virtual Proxy
根据需要将资源消耗很大的对象进行延迟真正需要的时候进行创建
保护代理
权限控制
智能引用代理
提供额外的服务 取代简单的指针,它在访问对象时执行一些附加操作
Copy-on-Write代理
虚拟代理的一种,把复制(克隆)操作延迟到只有客户端真正需要时才执行
两种实现方式
- 静态代理
- 动态代理
静态代理
代理和被代理对象在代理之前是确定的,他们实现相同的接口或者继承相同的抽象类
汽车行驶
package proxyDemo;
public interface Moveable {
void move();
}
package proxyDemo;
import java.util.Random;
public class Car implements Moveable {
@Override
public void move() {
long startTime = System.currentTimeMillis();
System.out.println("汽车开始行驶");
try {
System.out.println("汽车行驶中");
Thread.sleep(new Random().nextInt(1000)); //随即产生一个大于0小于1000的整数;用进程的例子模拟汽车行驶
} catch (InterruptedException e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
System.out.println("汽车结束行驶");
System.out.println("汽车行驶时间:"+(endTime-startTime)+"ms");
}
}
使用代理方式
import java.util.Random;
public class Car implements Moveable {
@Override
public void move() {
try {
System.out.println("汽车行驶中");
Thread.sleep(new Random().nextInt(10000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
package proxyDemo;
public class proxyCar extends Car {
@Override
public void move() {
long startTime = System.currentTimeMillis();
System.out.println("汽车开始行驶");
super.move();
long endTime = System.currentTimeMillis();
System.out.println("汽车结束行驶");
System.out.println("汽车行驶时间:"+(endTime-startTime)+"ms");
}
}
二者的测试类
package proxyDemo;
public class Test {
public static void main(String[] args) {
// Car benz = new Car();
// benz.move();
Moveable m = new proxyCar();
m.move();
}
}
- 抽象对象 声明了目标对象和代理对象的共同接口
- 目标对象 定义了代理对象所代表的目标对象
- 代理对象 内部含有目标对象的引用,从而在任何时候操纵目标对象,代理对象提供了与目标对象相同的接口,在任何时候可以替代目标对象.
##JDK动态代理##
java动态代理类位于java.lang.reflect包下,一般主要涉及两个类:
1.Interface InvocationHandler
public object invoke(Object obj,Method method,Object[] args)
这个抽象方法在代理类中动态实现
2.Proxy
static Object newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h)
返回代理类的一个实例,返回后的代理类可以当作被代理类使用
代码如下
package jdkproxy;
public interface Moveable {
void move();
}
package jdkproxy;
public class Car implements Moveable{
public void move()
{
System.out.println("---汽车行驶中---");
}
}
package jdkproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class TimeHandler implements InvocationHandler {
public TimeHandler(Object target) {
super();
this.target = target;
}
private Object target;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// TODO Auto-generated method stub
System.out.println("---时间处理---");
method.invoke(target);
System.out.println("---时间结束---");
return null;
}
}
package jdkproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
//JDK动态代理测试类
public class Test {
public static void main(String[] args) {
Car car = new Car();
InvocationHandler h = new TimeHandler(car);
Class<?> cls = car.getClass();
Moveable m =(Moveable)Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(),h);
m.move();
}
}
##cglib##
导入jar包,cglib-nodep-().jar
JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类,如何实现动态代理呢?
CGLIB是直接继承代理
性能:CGLib>JDK
时间耗费:JDK时间效率高
单例的对象使用CGLib
代码示例
public class SayHello {
public void say(){
System.out.println("hello everyone");
}
}
public class CglibProxy implements MethodInterceptor{
private Enhancer enhancer = new Enhancer();
public Object getProxy(Class clazz){
//设置需要创建子类的类
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
//通过字节码技术动态创建子类实例
return enhancer.create();
}
//实现MethodInterceptor接口方法
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
System.out.println("前置代理");
//通过代理类调用父类中的方法
Object result = proxy.invokeSuper(obj, args);
System.out.println("后置代理");
return result;
}
}
public class DoCGLib {
public static void main(String[] args) {
CglibProxy proxy = new CglibProxy();
//通过生成子类的方式创建代理类
SayHello proxyImp = (SayHello)proxy.getProxy(SayHello.class);
proxyImp.say();
}
}
##JDK动态代理的内部实现##
动态代理实现思路 实现功能:通过Proxy的newProxyInstance返回代理对象
- 声明一段源码(动态产生代理)
- 编译源码(JDK Compiler API),产生新的类(代理类)
- 将这个类load到内存当中,产生一个新的对象(代理对象)
- return 代理对象