代理模式分为静态代理和动态代理。静态代理其实我们经常用,比如我们在controller里面注入一个service的实例,需要的时候,调用service实例去做业务,就是静态代理的使用。也就是说,静态代理是:代理对象里面放一个被代理对象的实例,用代理对象去调用这个实例的方法。
下面用简洁通俗易懂的例子,去讲解一下动态代理。
我们先写一个被代理对象的接口和实现类。被代理的实现类是鸭子Duck,接口是Bird (鸭子是鸟类的一种)。接口:
public interface Bird {
String name="bird";
public void say();
}
实现类:
public class Duck implements Bird {
@Override
public void say() {
System.out.println("我是一只鸭子,嘎嘎嘎。I'm duck,ga ga ga ......1111111111111111");
}
}
再写一个鸭子的代理类。需要注意4点:
a. 代理类实现 InvocationHandler。
b.代理类有一个Object的属性,通过构造器注入被代理对象。
c. 在代理类里面的invoke方法进行对被代理对象的调用,及调用前后的额外处理(你想在调用前后干啥就干啥呗)。
d.写一个获取代理对象的get方法,方便获取代理对象。这个代理对象执行被代理对象的方法时,会执行invoke方法。
代理类:
public class DuckProxy implements InvocationHandler {
private Object duckObject;
public DuckProxy(Object duckObject) {
this.duckObject = duckObject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//在代理真实对象前我们可以添加一些自己的操作
System.out.println("在调用之前,我要干点啥呢?");
System.out.println("Method:" + method);
//当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
Object returnValue = method.invoke(duckObject, args);
//在代理真实对象后我们也可以添加一些自己的操作
System.out.println("在调用之后,我要干点啥呢?");
return returnValue;
}
public Object getDuckProxy(){
return Proxy.newProxyInstance(duckObject.getClass().getClassLoader(),
duckObject.getClass().getInterfaces(),this);
}
}
测试:
public class DuckPlay {
public static void main(String[] args){
Bird bird = new Duck();
Bird proxy=(Bird)new DuckProxy(bird).getDuckProxy();
proxy.say();
}
}
结果: