张三是一家建筑公司的老板,前些年承包项目挣了些钱,钱一多就没地儿花,于是就进入股市,不出意外的是出了意外,于是工头们纷纷前来要账~
先来看一个静态代理的例子
顾客到饭店吃饭,厨师负责做菜,那么就需要有人来帮厨师获取顾客点的菜,还有上菜
饭店
1 2 3 4 5 6 7
| package jdk.proxy;
public interface Restaurant {
void cooking(); }
|
厨师
1 2 3 4 5 6 7 8 9 10
| package jdk.proxy;
public class Cook implements Restaurant{
@Override public void cooking() { System.out.println("我是厨师:我负责做菜"); } }
|
厨师代理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| package jdk.proxy;
public class CookProxy implements Restaurant{
@Override public void cooking() {
System.out.println("我是服务员:顾客点菜");
Cook cook = new Cook(); cook.cooking();
System.out.println("我是服务员:上菜");
} }
|
测试
1 2 3 4 5 6 7 8 9 10
| package jdk.proxy;
public class TestCookProxy {
public static void main(String[] args) { CookProxy cookProxy = new CookProxy(); cookProxy.cooking(); } }
|
静态代理的缺点
因为代理类和被代理类实现相同的接口,所以代理类必须实现接口的全部方法,会出现冗余代码
每个代理类只能针对实现特定接口的被代理类,一个接口一个代理类
多个被代理类,则仍会出现冗余代码
JDK 动态代理
jdk 动态代理是基于接口实现的,也就是代理类和被代理类要实现共同的接口
利用 Proxy 创建代理类对象(被代理的类一定要实现某个接口),代理类通过实现 InvocationHandler 接口的增强器,通过执行 invoke 方法来增强被代理的方法
厨师
1 2 3 4 5 6 7 8 9 10
| package jdk.proxy;
public class Cook implements Restaurant{
@Override public void cooking() { System.out.println("我是厨师:我负责做菜"); } }
|
厨师代理类处理器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| package jdk.proxy;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method;
public class CookInvocationHandler implements InvocationHandler {
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("点菜");
Cook cook = new Cook(); method.invoke(cook,args);
System.out.println("上菜"); return null; } }
|
测试代理类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| package jdk.proxy;
import java.lang.reflect.Proxy;
public class TestCookProxyInvocation {
public static void main(String[] args) {
Cook cook = new Cook();
Restaurant restaurantProxy = (Restaurant)Proxy.newProxyInstance(cook.getClass().getClassLoader(), cook.getClass().getInterfaces(), new CookInvocationHandler()); restaurantProxy.cooking(); } }
|
newProxyInstance 方法:
参数1:被代理类的类类加载器
参数2:被代理类实现的接口列表
参数3:实现 InvocationHanler 接口的调用处理器,代理类增强方法实际用功处
完