代理模式定义:为其他对象提供一种代理一控制对这个对象的访问。代理对象起到中介作用,可以去掉功能服务或者增加额外服务。
例如:买火车票,去售票处。常见几种代理模式:
- 远程代理:为不同地理的对象提供局域网代表对象
- 虚拟代理:根据需要将资源消耗很大的对象进行延迟真正需要的时候进行创建。
- 保护代理:就是权限管理。
- 智能代理:就是增加额外功能。
静态代理
静态代理:代理和被代理对象在代理之前是确定的。他们都实现相同的接口或者继承相同的抽象类。
例子:如何用代理计算汽车行驶时间
package com.example.proxy;
public interface Moveable {
void move();
}
package com.example.proxy;
import javax.swing.plaf.basic.BasicInternalFrameTitlePane.MoveAction;
public class Car implements Moveable {
@Override
public void move() {
// TODO Auto-generated method stub
for(int i = 0;i<1000;i++){
System.out.println("汽车正在行驶");
}
}
}
静态代理实现方式
- 继承
package com.example.proxy;
public class Car1 extends Car{
@Override
public void move() {
// TODO Auto-generated method stub
long start = System.currentTimeMillis();
super.move();//执行父类方法,也就是car方法
long end = System.currentTimeMillis();
System.out.println(end-start);
}
}
- 聚合
package com.example.proxy;
public class Car2 implements Moveable {
private Car c;
public Car2(Car c) {
super();
this.c = c;
}
@Override
public void move() {
// TODO Auto-generated method stub
long start = System.currentTimeMillis();
c.move();
long end = System.currentTimeMillis();
System.out.println(end-start);
}
}
继承和聚合哪种方式更适合
我们在上述的功能,在添加一个功能,来比较两种方式。
按照上面添加功能,每增加一个功能,就要多写一个类来继承。
下面是聚合方式,比较灵活,代码如下:
public class CarLog implements Moveable {
private Moveable c ;
public CarLog(Moveable c) {
super();
this.c = c;
}
@Override
public void move() {
// TODO Auto-generated method stub
System.out.println("行车日志开始");
c.move();
System.out.println("行车日志结束");
}
}
JDK动态代理
在上述功能中,如果每添加一个对象的代理,就要写一个代理类,这样的代理类会爆炸,我们就思考:动态产生代理,实现对不同类,不同方法的代理。
实现方式:就是在代理类和被代理类加事务处理器
代码如下:
public class Car implements Moveable {
@Override
public void move() {
// TODO Auto-generated method stub
for(int i = 0;i<1000;i++){
System.out.println("汽车正在行驶");
}
}
}
事务处理器
public class CarProxy implements InvocationHandler {
private Object target;
public CarProxy(Object target) {
super();
this.target = target;
}
/*
* (non-Javadoc)
* @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
* proxy 指被代理的类
* method 被代理的方法
* args 方法的参数
* 方法返回Object ,就是执行代理返回方法。
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
long start = System.currentTimeMillis();
method.invoke(target);//这个方法是传入目标代理类,和参数,参数可以没有。
long end = System.currentTimeMillis();
System.out.println(end-start);
return null;
}
}
测试类
public class TestCar {
@Test
public void test() {
/*Car c = new Car();
Car2 c2 = new Car2(c);
CarLog cl = new CarLog(c2);
cl.move();*/
Car c1 = new Car();
Class<Car> c = (Class<Car>) c1.getClass();
CarProxy cp = new CarProxy(c1);
/*newProxyInstance参数
* loader 类加载器
* interfaces 实现接口
* h InvocationHandler
*/
Moveable m = (Moveable) Proxy.newProxyInstance(c.getClassLoader(),c.getInterfaces(),cp);
m.move();
}
}
JDK动态代理与CGLIB动态代理区别:
JDK动态代理:只能代理实现接口的类,,没有实现接口的类不能实现JDK的动态代理。CGLIB动态代理:代理继承的类,对指定目标类产生一个子类,通过方法拦截技术拦截所有父类方法的调用。
CGLIB代理代码如下:
首先导入cglib的jar包
public class Train {
public void move() {
// TODO Auto-generated method stub
System.out.println("火车正在开");
}
}
package com.example.proxy;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CglibProxy implements MethodInterceptor {
Enhancer enhancer = new Enhancer();
/*
* 该方法来创建代理类
*/
public Object getProxy(Class cal){
enhancer.setSuperclass(cal);
enhancer.setCallback(this);
return enhancer.create();
}
/*
* (non-Javadoc)
* @see net.sf.cglib.proxy.MethodInterceptor#intercept(java.lang.Object, java.lang.reflect.Method, java.lang.Object[], net.sf.cglib.proxy.MethodProxy)
* arg0 目标类实例
* arg1 目标方法的反射对象
* arg2 方法参数
* arg3 代理器实例
*/
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2,
MethodProxy arg3) throws Throwable {
// TODO Auto-generated method stub
System.out.println("日志开始");
arg3.invokeSuper(arg0, arg2);//代理器实例调用父类方法
return null;
}
}
CglibProxy c = new CglibProxy();
Train t = (Train) c.getProxy(Train.class);
t.move();