代理模式的定义:给某一个对象提供一个代理,并由代理对象控制对原对象的引用。在实际生活中,也有代理,例如:房地产中介,明星的经纪人。
代理模式包含如下角色:
ISubject:抽象主题角色,是一个接口。该接口是对象和它的代理共用的接口。
RealSubject:真实主题角色,是实现抽象主题接口的类。
Proxy:代理角色,内部含有对真实对象RealSubject的引用,从而可以操作真实对象。代理对象提供与真实对象相同的接口,以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。
代理模式的实现思路:
1.代理对象和目标对象均实现同一个行为接口。
2.代理类和目标类分别具体实现接口逻辑。
3.在代理类的构造函数中实例化一个目标对象。
4.在代理类中调用目标对象的行为接口。
5.客户端想要调用目标对象的行为接口,只能通过代理类来操作。
代理模式有静态代理和动态代理。
实现动态代理的关键技术是反射。同时,代理模式也是Spring AOP的核心机制之一。
1.静态代理。
静态代理是由程序员编写的代理类,并在程序运行前就编译好的,而不是由程序动态产生代理类,这就是所谓的静态。
/**
* 抽象主题接口
*/
public interface Manager {
void doSomething();
}
/**
* 真实主题对象
*/
public class Admin implements Manager{
@Override
public void doSomething() {
System.out.println("Admin.doSomething()");
}
}
/**
* 代理对象
*/
public class ManngerProxy implements Manager{
private Admin admin;
public ManngerProxy(Admin admin) {
super();
this.admin = admin;
}
@Override
public void doSomething() {
System.out.println("打印日志开始。。。");
admin.doSomething();
System.out.println("打印日志结束。。。");
}
}
/**
* 客户端测试
*/
public class ClientTest {
public static void main(String[] args) {
Admin admin=new Admin();
ManngerProxy proxy=new ManngerProxy(admin);
proxy.doSomething();
}
}
测试结果:
打印日志开始。。。
Admin.doSomething()
打印日志结束。。。
由于静态代理需要事先写好代理类,当业务逻辑复杂的时候就会非常麻烦,也非常的不灵活,相比静态代理,动态代理具有更强的灵活性。
2.动态代理
动态代理是指在运行时动态生成代理类。即,代理类的字节码将在运行时生成并载入当前代理的 ClassLoader。
生成动态代理的方法有很多: JDK中自带动态代理, CGlib, javassist等。这些方法各有优缺点。本文主要记录JDK中的动态代理的使用。
/**
* 抽象主题接口
*/
public interface Moveable {
void move()throws Exception;
}
/**
* 真实主题对象
*/
public class Car implements Moveable {
@Override
public void move() throws Exception {
Thread.sleep(new Random().nextInt(1000));
System.out.println("Car:汽车行驶中。。。");
}
}
/**
* 事务处理类
*/
public class TimerHandler implements InvocationHandler {
private Object target;
public TimerHandler(Object target) {
super();
this.target = target;
}
/* 参数:
* proxy:被代理的对象
* method:被代理对象的方法
* args:方法的参数
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
long start_time = System.currentTimeMillis();
System.out.println("汽车开始行驶。。。");
method.invoke(target, args);
long end_time = System.currentTimeMillis();
System.out.println("汽车行驶结束。。。");
System.out.println("汽车行驶时间:"+(end_time-start_time)+"毫秒");
return null;
}
}
/**
* 客户端测试
*/
public class ClientTest {
public static void main(String[] args) throws Exception {
Car car=new Car();
InvocationHandler h=new TimerHandler(car);
Class<?> clz = car.getClass();
/*
* Proxy.newProxyInstance()方法的参数:
* loader:类加载器
* interfaces:实现接口
* h:InvocationHandler
*/
Moveable m = (Moveable) Proxy.newProxyInstance(clz.getClassLoader(), clz.getInterfaces(), h);
m.move();
}
}
测试结果:
汽车开始行驶。。。
Car:汽车行驶中。。。
汽车行驶结束。。。
汽车行驶时间:456毫秒