代理模式分为静态代理和动态代理:我们首先来看一下静态代理模式:
有这样一种场景,爸爸想抽烟,可是自己又不想去买于是他就叫他自己的儿子代他去买香烟;这是儿子就是代理类而爸爸就是被代理对象,我们看下这个场景的代码
package com.djk.design.Proxy;
/**
* 代理模式
* @author djk
*
*/
public class ProxyTest1
{
public static void main(String[] args)
{
Shopping shopping = new Son();
Father father = new Father();
father.setShopping(shopping);
father.buyCigarette();
}
}
/**
* 购物接口
* @author djk
*
*/
interface Shopping
{
void buyCigarette();
}
/**
* 父亲
* @author djk
*
*/
class Father implements Shopping
{
private Shopping shopping;
public Shopping getShopping() {
return shopping;
}
public void setShopping(Shopping shopping) {
this.shopping = shopping;
}
public void buyCigarette()
{
if(null == shopping)
{
System.out.println("爸爸太懒自己不去买,叫儿子去买...");
return ;
}
shopping.buyCigarette();
}
}
class Son implements Shopping
{
public void buyCigarette()
{
System.out.println("儿子买香烟");
}
}
静态代理和策略模式看上去差不多,其实他们还是有差别的,细心的可以发现静态代理的被代理类和代理类都实现了同一个接口,而策略模式中不需要实现同一个接口。
接下来就讲一下jdk的动态代理:现在有一辆车,他有一个开车的方法,现在我想在他开车这个方法前和后加入一些日志,这个时候就能用动态代理:
package com.djk.design.Proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 动态代理
* @author djk
*
*/
public class ProxyTest2
{
public static void main(String[] args)
{
Moveable moveable1 = new CarMove();
InvocationHandler invocationHandler = new ProxyCar(moveable1);
Moveable moveable =(Moveable) Proxy.newProxyInstance(moveable1.getClass().getClassLoader(), moveable1.getClass().getInterfaces(), invocationHandler);
moveable.move();
}
}
/**
* 移动接口
* @author djk
*
*/
interface Moveable
{
void move();
}
/**
* 汽车 被代理对象
* @author djk
*
*/
class CarMove implements Moveable
{
public void move()
{
System.out.println("汽车行驶中");
}
}
/**
* 在代理对象中的引用类
* @author djk
*
*/
class ProxyCar implements InvocationHandler
{
//被代理对象
private Object object;
public ProxyCar(Object object)
{
this.object = object;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("汽车准备启动。。。");
method.invoke(object, new Object [] {});
System.out.println("汽车停止了。。。");
return null;
}
}
上面是JDK的动态代理。我们用JDK动态代理的时候要注意代理对象一定要实现某一个接口后才能被代理。其实这里面运用到了反射,真正执行的是一个代理对象,这个代理对象需要注入一个实现了InvocationHandler接口的对象,然后其实最终是由jdk的代理类来执行了里面InvocationHandler实现类里面的具体方法,这个InvocationHandler的实现类则是由我们来提供的,在这个实现类里面利用到了反射机制来在运行期执行调用的方法,反射调用方法的时候需要一个参数是哪个对象的方法,所以这个实现类中需要注入被代理对象,说明是反射执行了这个被代理类的这个方法,在这个方法前面和后面我们可以加自己想要加的东西。。。
代理模式用的很广泛,struts2就用到了代理模式,其实我们自己的action并没有真正的去做事,而是由struts2的ActionProxy去反射执行了action中的方法,spring的aop也利用了动态代理的思想来实现了aop切面。。。。