代理模式
概念:为其他对象提供一种代理,控制对这个对象的访问,代理对象起到了中介的作用,去掉了某些功能,或者是增加了一些额外的服务
应用场景:火车票代售处购买火车票,火车票代售处就是火车站的代理
代理分类
虚拟代理、智能代理、远程代理、保护代理
智能代理(开发中最常见):比如,日志处理、权限管理、事务处理等。
代理实现方式:
静态代理:代理和被代理对象在代理之前是确定的,他们都实现相同的接口或者继承相同的抽象类
静态代理实现方式:
继承代理:通过继承需要代理的类,在子类调用父类,在调用前后记录日志
public class Car implements Moveable
{
@Override
public void move()
{
try
{
Thread.sleep(new Random().nextInt(1000));
System.out.println("汽车正在行驶。。。");
Thread.sleep(new Random().nextInt(1000));
} catch (Exception e)
{
e.printStackTrace();
}
}
}
/**
* 使用继承方式实现代理
*/
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("汽车结束行驶,共行驶时间:" + (endTime - startTime) + "毫秒");
}
}
Test:
//继承方式代理
// ProxyCar proxyCar=new ProxyCar();
// proxyCar.move();
聚合代理:代理类和被代理类,都要实现相同接口,被代理类作为代理类的成员变量,通过构造器传入代理类,在代理类中调用被代理类方法
/**
* 一个类有一个类的实体引用(类中的类),则它称为聚合
*/
public class ProxyCar2 implements Moveable
{
private Car car;
public ProxyCar2(Car car)
{
this.car = car;
}
@Override
public void move()
{
long startTime = System.currentTimeMillis();
System.out.println("汽车开始行驶。。。");
car.move();
long endTime = System.currentTimeMillis();
System.out.println("汽车结束行驶,共行驶时间:" + (endTime - startTime) + "毫秒");
}
}
Test:
//聚合方式代理
// Car car=new Car();
//// ProxyCar2 proxyCar2=new ProxyCar2(car);
//// proxyCar2.move();
动态代理
实现对不同类,不同方法代理
ProxyHandler:代理类和被代理类之间加入实现InvocationHandler的类ProxyHandler
Proxy:该类即为动态代理类,
Class cls=car.getClass();
Moveable m= (Moveable) Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(),ih);
返回代理类的一个实例,返回后的代理类可以当作被代理类使用(可使用被代理类在接口中声明过的方法)
JDK动态代理
JDK动态代理实现的前提条件
1.被代理类需要实现某个interface,为什么?
由于java的单继承,动态生成的代理类已经继承了Proxy类的,就不能再继承其他的类,所以只能靠实现被代理类的接口的形式,故JDK的动态代理必须有接口
动态代理的思路便是根据我们传入的参数生成一个新类
2.代理类,必须实现InvocationHandler接口
动态代理实现步骤:
1.创建一个实现InvocationHandler接口的类,它必须实现invoke方法
public class TimeHandler implements InvocationHandler
{
private Object target;
public TimeHandler(Object target)
{
this.target = target;
}
/**
* @param proxy 被代理对象
* @param method 被代理对象方法
* @param args 被代理对象方法参数
* @return 方法返回值
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
long startTime = System.currentTimeMillis();
System.out.println("汽车开始行驶。。。");
method.invoke(target);
long endTime = System.currentTimeMillis();
System.out.println("汽车结束行驶,共行驶时间:" + (endTime - startTime) + "毫秒");
return null;
}
2.创建被代理类和接口
3.调用Proxy的静态方法,创建一个代理类对象
public static void main(String[] args)
{
Car car=new Car();
InvocationHandler ih=new TimeHandler(car);
Class cls=car.getClass();
/**
* 参数1:类加载器
* 参数2:实现接口
* 参数3:实现的处理器
*/
Moveable m= (Moveable) Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(),ih);
System.out.println(m.getClass().getName());
m.move();
}
4.通过代理类对象调用方法
CGLIB动态代理
public class Train
{
public void move(){
System.out.println("火车行驶中...");
}
}
public class CglibProxy implements MethodInterceptor
{
private Enhancer enhancer=new Enhancer();
public Object getProxy(Class clazz){
//设置创建子类的类,也就是为哪个类产生代理类
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);//回调
return enhancer.create();//创建子类实例
}
/**
* 拦截所有目标类方法的调用
* @param obj 目标类的实例
* @param method 目标方法反射对象
* @param args 方法参数
* @param proxy 代理类实例
* @return
* @throws Throwable
*/
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable
{
System.out.println("日志开始...");
//代理类调用父类方法,cglib使用继承方式,所有代理类是父类子类
proxy.invokeSuper(obj,args);
System.out.println("日志结束...");
return null;
}
public static void main(String[] args)
{
CglibProxy proxy=new CglibProxy();
Train train= (Train) proxy.getProxy(Train.class);
train.move();
}
注意:CGLIB是invokeSuper别调错了
所需jar包,只有cglib的jar包还不够,还需要asm的jar包,可取maven仓库下载
JDK动态代理和CGLIB动态代理区别
JDK动态代理:1.只能代理实现接口的类 2.没有实现接口的类不能实现jdk动态代理
CGLIB动态代理:1.针对类实现代理 2.原理对指定目标类产生一个子类,覆盖其中方法实现功能增强 3.因为是继承所以不能对final修饰的类进行代理
本文暂时没有评论,来添加一个吧(●'◡'●)