前言
java的代理机制,包括静态代理和动态代理
静态代理和动态代理中都有使用到接口
关于接口,个人认为需要意识到以下几点:
1.一个类继承了类A和执行了接口B,A与B在同一层级
2.接口的使用体现代码的多态性
3.接口体现的是代码的规范性,在现实生活中就是”如果你要….,就必须要……“
正文
静态代理机制
例子:小明做饭需要买鱼和买鸡蛋,但是小明没有空,于是小明托小红,小兰去帮忙买鱼和鸡蛋。
在这个例子里小明作为被代理类,小红,小兰作为代理类,将帮小明分别去买这两样东西,因为代理类和被代理类的目的买这些东西,所以这里实现两个接口。
1 2 3 4 5 6 7
| interface Buyfish{ void payForFish(); }
interface Buyegg{ void payForegg(); }
|
然后想要买鱼和鸡蛋的但是腿脚不便的人需要做的事
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class BuyFishPeople implements Buyfish{
@Override public void payForFish() { System.out.println("为买鱼付了60元"); } }
class BuyeggPeople implements Buyegg{
@Override public void payForegg() { System.out.println("为买鸡蛋付了60元"); } }
|
帮忙买鱼和鸡蛋的人需要做的事
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| class ProxyBuyFish implements Buyfish{ private Buyfish obj; public ProxyBuyFish(Buyfish obj){ System.out.println("去海鲜市场"); this.obj = obj; }
@Override public void payForFish() { obj.payForFish(); } }
class ProxyBuyegg implements Buyegg{
private Buyegg obj; public ProxyBuyegg(Buyegg obj){ this.obj=obj; } @Override public void payForegg(){ System.out.println("去买鸡蛋的超市"); obj.payForegg(); } }
|
主程序中
1 2 3 4 5 6 7 8 9 10
| public void test(){ BuyFishPeople xiaoming = new BuyFishPeople(); ProxyBuyFish xiaohong = new ProxyBuyFish(xiaoming); xiaohong.payForFish();
BuyeggPeople xiaoming2 = new BuyeggPeople(); ProxyBuyegg xiaolan = new ProxyBuyegg(xiaoming2); xiaolan.payForegg();
}
|
全部代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
| package com.c0okb.ProxyTest;
import org.junit.Test;
interface Buyfish{
void payForFish(); }
class BuyFishPeople implements Buyfish{
@Override public void payForFish() {
System.out.println("买鱼付了60元"); } }
class ProxyBuyFish implements Buyfish{ private Buyfish obj; public ProxyBuyFish(Buyfish obj){ System.out.println("去海鲜市场"); this.obj = obj; }
@Override public void payForFish() { obj.payForFish(); } }
interface Buyegg{
void payForegg(); }
class BuyeggPeople implements Buyegg{
@Override public void payForegg() {
System.out.println("为买鸡蛋付了60"); } }
class ProxyBuyegg implements Buyegg{
private Buyegg obj; public ProxyBuyegg(Buyegg obj){ this.obj=obj; } @Override public void payForegg(){ System.out.println("去买鸡蛋的超市"); obj.payForegg(); } }
public class DynamicProxyTest2 {
@Test public void test(){ BuyFishPeople xiaoming = new BuyFishPeople(); ProxyBuyFish xiaohong = new ProxyBuyFish(xiaoming); xiaohong.payForFish();
BuyeggPeople xiaoming2 = new BuyeggPeople(); ProxyBuyegg xiaolan = new ProxyBuyegg(xiaoming2); xiaolan.payForegg(); }
}
|
但是静态代理有一个很严重的问题,每一个代理只能完成一种需求,假如小明还想买鸡鸭鹅狗猫,那他还需要叫更多人。在代码中就显得这很繁琐。
于是提出动态代理机制
动态代理机制
动态代理中有两个问题需要解决
1 2 3
| 问题一:如何根据加载到内存中的被代理类,动态的创建一个代理类及其对象。 问题二:当通过代理类的对象调用方法时,如何动态地去调用被代理类中的同名方法。
|
小明的需求不变
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| interface Buyfish{
void payForFish(); }
class BuyFishPeople implements Buyfish{
@Override public void payForFish() { System.out.println("买鱼付了60元"); } }
interface Buyegg{
void payForegg(); }
class BuyeggPeople implements Buyegg{
@Override public void payForegg() {
System.out.println("为买鸡蛋付了60"); } }
|
这时候帮忙买东西的人需要完成的事
1 2 3 4 5 6 7 8 9
| class ProxyFactory1{ public static Object getProxy(Object obj){ BuyMyInvocationHandler handler = new BuyMyInvocationHandler(); handler.bind(obj); return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),handler); } }
|
在代理类中实现方法getProxy(Object obj)
,这个方法中的参数obj
就是我们需要被代理的类。这个方法将会返回一个被代理类的对象。
其中关键的函数
1
| Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),handler);
|
其中
1 2
| obj.getClass().getClassLoader() 获得被代理类的类加载器 obj.getClass().getInterfaces() 获得被代理类实现的接口
|
最后一个参数handler
1 2
| BuyMyInvocationHandler handler = new BuyMyInvocationHandler(); handler.bind(obj);
|
这是我们自己创建的类,用于调用被调用类的指定方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class BuyMyInvocationHandler implements InvocationHandler{ private Object obj; public void bind(Object obj){ this.obj = obj; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object ReturnValue = method.invoke(obj,args); return ReturnValue; } }
|
这个类实现接口InvocationHandler
,该接口中的方法如下,在实现该接口情况下,我们重写这个方法
1 2 3 4
| public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object ReturnValue = method.invoke(obj,args); return ReturnValue; }
|
动态代理中有两个问题需要解决
1 2 3 4
| 问题一:如何根据加载到内存中的被代理类,动态的创建一个代理类及其对象。 通过创建方法 public static Object getProxy(Object obj) 实现动态创建代理类 问题二:当通过代理类的对象调用方法时,如何动态地去调用被代理类中的同名方法。 通过 class BuyMyInvocationHandler implements InvocationHandler 这个类来实现动态,调用被代理类的同名方法
|
主程序
1 2 3 4 5 6 7 8
| public void test(){ BuyFishPeople xiaoming = new BuyFishPeople(); BuyeggPeople xiaoming2 = new BuyeggPeople(); Buyfish xiaohong = (Buyfish) ProxyFactory1.getProxy(xiaoming); Buyegg xiaohong2 = (Buyegg) ProxyFactory1.getProxy(xiaoming2); xiaohong.payForFish(); xiaohong2.payForegg(); }
|
当我们执行
将会调用
1 2 3 4
| public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object ReturnValue = method.invoke(obj,args); return ReturnValue; }
|
全部代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
| package com.c0okb.ProxyTest;
import org.junit.Test;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy;
interface Buyfish{
void payForFish(); }
class BuyFishPeople implements Buyfish{
@Override public void payForFish() { System.out.println("买鱼付了60元"); } }
interface Buyegg{
void payForegg(); }
class BuyeggPeople implements Buyegg{
@Override public void payForegg() {
System.out.println("为买鸡蛋付了60"); } }
class ProxyFactory1{
public static Object getProxy(Object obj){ BuyMyInvocationHandler handler = new BuyMyInvocationHandler(); handler.bind(obj); return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),handler); }
}
class BuyMyInvocationHandler implements InvocationHandler{ private Object obj; public void bind(Object obj){ this.obj = obj; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object ReturnValue = method.invoke(obj,args); return ReturnValue; } }
public class DynamicProxyTest2 {
public void test(){ BuyFishPeople xiaoming = new BuyFishPeople(); BuyeggPeople xiaoming2 = new BuyeggPeople(); Buyfish xiaohong = (Buyfish) ProxyFactory1.getProxy(xiaoming); Buyegg xiaohong2 = (Buyegg) ProxyFactory1.getProxy(xiaoming2); xiaohong.payForFish(); xiaohong2.payForegg(); } }
|