Java代理模式

Posted 1234ztc

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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             @Override
32 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代理模式的主要内容,如果未能解决你的问题,请参考以下文章

Java设计模式-代理模式之动态代理(附源代码分析)

java代理模式

JAVA设计模式 -- 代理模式

Java 代理模式讲解

代理模式(动态)

Java业务代理模式~