首页 > 代码库 > Java代理模式
Java代理模式
关于代理模式的概念:
用现在相当热门的宝强马蓉事件做比喻,宝强相当于是被代理类,宋喆就是代理类,宋喆代理着宝强的许多行为,宋喆对宝强的消息进行预处理、过滤、转发、公关等。就如公关,当宝强需要公关的时候宝强无须真正亲自去实现公关,真正实现的是由宋喆代理完成。
代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类 与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。
静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。
动态代理:在程序运行时,运用反射机制动态创建而成。
首先我们使用代码来讲解静态代理:
以下是IStar类型接口,也就是明星该有的行为:
1 public interface IStar{2 //努力工作3 void hardWork;4 //爱妻子5 void loveWife;6 }
以下是IStar接口的实现类Satr
public class Star implementsIStar{ private String mName; public Star(String mName){ mName=this.mName; } public void hardWork(){ System.out.printf(this.mName+"努力工作");} public void loveWife(){ System.out.printf(this.mName+"爱护妻子");} }
经纪人代表的是明星,所以从某种意义上讲与明星具有相同的行为
public class Agent implements IStar{ //需要代理的对象 IStar mIStar; //代理类的一个成员变量 boolean mIsHappy; public Agent(IStar IStar){ mIStar=IStar; } public Agent(IStar IStar,boolean isHappy){ mIStar=IStar; mIsHappy=isHappy; } //与被代理类具有相同方法 public void hardWork(){ mIStar.hardWork;} //此时代理类也可以改变被代理类的行为方法 public void loveWife(){ if(mIsHappy){ mIStar.loveWife; }else{ System.out.printf("经纪人造反"); }} }
测试类
public class test{ public static void main(String[] args){ //在此新建一个被代理对象 是明星王宝强 Star baoqiang=new Star("王宝强"); //告诉经纪人 他需要代理的对象是明星王宝强 并且将经济人IsHappy属性设 // 为false Agent songjj =new Agent(baoqiang,false); songjj.hardWrok(); songjj.loveWife();}}
输出结果:王宝强努力工作
经纪人造反
以上是静态代理的例子,有助于代码的解耦。
接下来是动态代理模式:
要求如下:使用java代码完成整数加减乘除算法器,并且
1、在程序执行期间追踪正在发生的活动
2、希望计算器只能处理正数的运算
为了是的代码的集中与不混了我们使用动态代理模式实现
首先是创建一个接口
1 public interface ArithmeticCalculator {2 3 int add(int i, int j);4 int sub(int i, int j);5 6 int mul(int i, int j);7 int div(int i, int j);8 9 }
其次是实现ArithmeticCalculator接口
public class ArithmeticCalculatorImpl implements ArithmeticCalculator { @Override public int add(int i, int j) { int result = i + j; return result; } @Override public int sub(int i, int j) { int result = i - j; return result; } @Override public int mul(int i, int j) { int result = i * j; return result; } @Override public int div(int i, int j) { int result = i / j; return result; }}
穿件代理类ArithmeticCalculatorLoggingProxy
1 1 package com.atguigu.spring.aop; 2 2 3 3 import java.lang.reflect.InvocationHandler; 4 4 import java.lang.reflect.Method; 5 5 import java.lang.reflect.Proxy; 6 6 import java.util.Arrays; 7 7 8 8 public class ArithmeticCalculatorLoggingProxy { 9 9 10 10 //要代理的对象11 11 private ArithmeticCalculator target;12 12 13 13 public ArithmeticCalculatorLoggingProxy(ArithmeticCalculator target) {14 14 super();15 15 this.target = target;16 16 }17 17 18 18 //返回代理对象19 19 public ArithmeticCalculator getLoggingProxy(){20 20 ArithmeticCalculator proxy = null;21 21 //获取要代理对象的加载器22 22 ClassLoader loader = target.getClass().getClassLoader();23 23 Class [] interfaces = new Class[]{ArithmeticCalculator.class};24 25 24 InvocationHandler h = new InvocationHandler() {26 25 /**27 26 * proxy: 代理对象。 一般不使用该对象28 27 * method: 正在被调用的方法29 28 * args: 调用方法传入的参数30 29 */31 30 @Override32 31 public Object invoke(Object proxy, Method method, Object[] args)33 32 throws Throwable {34 33 String methodName = method.getName();35 34 //打印日志36 35 System.out.println("[before] The method " + methodName + " begins with " + Arrays.asList(args));37 36 38 37 //调用目标方法39 38 Object result = null;40 39 41 40 try {42 41 //前置通知43 42 result = method.invoke(target, args);44 43 //返回通知, 可以访问到方法的返回值45 44 } catch (NullPointerException e) {46 45 e.printStackTrace();47 46 //异常通知, 可以访问到方法出现的异常48 47 }49 48 50 49 //后置通知. 因为方法可以能会出异常, 所以访问不到方法的返回值51 50 52 51 //打印日志53 52 System.out.println("[after] The method ends with " + result);54 53 55 54 return result;56 55 }57 56 };58 57 59 58 /**60 59 * loader: 代理对象使用的类加载器。 61 60 * interfaces: 指定代理对象的类型. 即代理代理对象中可以有哪些方法. 62 61 * h: 当具体调用代理对象的方法时, 应该如何进行响应, 实际上就是调用 InvocationHandler 的 invoke 方法63 62 */64 63 proxy = (ArithmeticCalculator) Proxy.newProxyInstance(loader, interfaces, h);65 64 66 65 return proxy;67 66 }68 67 }
测试类
1 package com.atguigu.spring.aop; 2 3 import org.springframework.context.ApplicationContext; 4 import org.springframework.context.support.ClassPathXmlApplicationContext; 5 6 public class Main { 7 8 public static void main(String[] args) { 9 ArithmeticCalculator arithmeticCalculator = new ArithmeticCalculatorImpl();10 11 arithmeticCalculator = 12 new ArithmeticCalculatorLoggingProxy(arithmeticCalculator).getLoggingProxy();13 14 int result = arithmeticCalculator.add(11, 12);15 System.out.println("result:" + result);16 17 result = arithmeticCalculator.div(21, 3);18 System.out.println("result:" + result);19 20 }21 22 }
Java代理模式