什么是代理呢,就好比经纪人和演员的关系,有些事情不用演员做,经纪人就直接动手了,也就是说在不访问被代理类的情况下去调用其相关方法。
Java代理分为静态代理和动态代理
静态代理就是和被代理类实现统一接口,然后调用其方法,如果我们在编译时就知道是代理哪个对象 就可以使用静态代理
首先创建一个接口Animal
/** * @author chunying */ public interface Animal { void eat(); void run(); }
然后是实现类Cat
/** * @author chunying */ //被代理类 public class Cat implements Animal{ @Override public void eat() { System.out.println("猫吃鱼"); } @Override public void run() { System.out.println("喵喵叫"); } } 静态代理类
/** * @author chunying */ public class StaticProxy implements Animal{ private Animal animal; public StaticProxy(Animal animal) { this.animal = animal; } @Override public void eat() { animal.eat(); } @Override public void run() { animal.run(); } }
测试
@Test public void fun3() { Cat c = new Cat(); StaticProxy staticProxy = new StaticProxy(c); staticProxy.eat(); staticProxy.run(); }
最终输出
猫吃鱼
喵喵叫
接下来看动态代理
Animal 和 Cat不变
代理对象需要实现InvocationHandler接口 实现方法invoke
/** * @author chunying */ public class MyInvocationHandler implements InvocationHandler{ private Object target; public MyInvocationHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { method.invoke(target, args); return null; } }
我们在执行被代理类的方法时 最终都是调用了这个方法,所以可以在这个类中对方法进行一些扩展
测试
@Test public void fun2() { Cat cat = new Cat(); Class<?>[] interfaces = cat.getClass().getInterfaces(); MyInvocationHandler myInvocationHandler = new MyInvocationHandler(cat); ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); Animal proxy = (Animal)Proxy.newProxyInstance(classLoader, interfaces, myInvocationHandler); proxy.eat(); proxy.run(); }
最终输出是一样的 这里我们创建了一个代理对象,调用了Proxy.newProxyInstance()
这个方法有三个参数,第一个是指定的类加载器,第二个是指明被代理类实现的接口,第三个这是一个方法委托类,我们通过代理调用被代理类的方法时,就可以将方法名和方法参数都委托给这个委托类。
所以有了类加载器,实现的方法,代理的对象,这样执行一个被代理类的方法就很简单了。