代理-静态代理和动态代理

静态代理

  

1、接口类

1 public interface Star {
2     public void sing();
3 }

2、被代理类

1 public class Liyuchun implements Star {
2     public void sing() {
3         System.out.println("春哥唱歌");
4     }
5 }

3、代理类

 1 public class LiyuchunProxy implements Star {
 2     private Liyuchun liyuchun = new Liyuchun();
 3     public void sing() {
 4         liyuchun.sing();
 5     }
 6     //基于接口编程
 7     public Star getProxy() {
 8         return liyuchun;
 9     }
10 }

4、用户

 1 //哥/歌迷
 2 public class Fans {
 3     public static void main(String[] args) {
 4         //创建代理对象
 5         LiyuchunProxy liyuchunProxy = new LiyuchunProxy();
 6         //通过代理对象找目标对象
 7         Star star = liyuchunProxy.getProxy();
 8         //业务方法
 9         star.sing();
10     }
11 }

 动态代理

  动态代理(代理类产生代理对象)

明确两个概念:
•代理对象存在的价值:主要用于拦截对真实业务对象的访问。
•代理对象有什么方法?与真实对象相同,只是无业务代码。

  现在要生成某一个对象的代理对象,这个代理对象通常也要编写一个类来生成,所以首先要编写用于生成代理对象的类,即代理类的对象。

  如何编写生成代理对象的类,两个要素:

•代理谁
•如何生成代理对象
代理谁?
  •设计一个类变量,以及一个构造函数,记住代理类代理哪个对象。

如何生成代理对象?(invoke方法)

  •设计一个方法生成代理对象(在方法内编写代码生成代理对象是此处编程的难点)

      

 

Java提供了一个Proxy类,调用它的newInstance()方法可以生成某个对象的代理对象,使用该方法生成代理对象时,需要三个参数:
•1.生成代理对象使用哪个类加载器ClassLoader
•2.生成哪个对象的代理对象,通过接口指定
•3.生成的代理对象的方法里干什么事,由开发人员编写handler接口的实现来指定。
 
初学者必须记住的2件事情:
•Proxy类负责创建代理对象时,如果指定了handler(处理器),那么不管用户调用代理对象的什么方法,该方法都是调用处理器的invoke方法。
•由于invoke方法被调用需要三个参数:代理对象、方法、方法的参数,因此不管代理对象哪个方法调用处理器的invoke方法,都必须把自己所在的对象、自己(调用invoke方法的方法)、方法的参数传递进来。
 
开发步骤:

1)写一个普通类,无需任何继承或实现
2)写一个实例变量,记住代理谁,即目标对象
3)使用构造方法为实例变量赋值
4)写一个普通方法,该方法的返回值是接口,该接口是目标对象的实现接口

1、接口类

1 public interface Star {
2     
3     public void sing();
4     public void sing(String money);
5 }

 

2、被代理类

1 //    目标对象
2 public class Liyuchun implements Star {
3     public void sing() {
4         System.out.println("春哥唱歌");
5     }
6     public void sing(String money){
7         System.out.println("春哥的"+money+"万出场费,春哥开始唱歌了");
8     }
9 }

 

3、代理类

 1 import java.lang.reflect.InvocationHandler;
 2 import java.lang.reflect.Method;
 3 import java.lang.reflect.Proxy;
 4 
 5 //    代理类
 6 public class LiyuchunProxy {
 7 
 8 //    代理谁,通过构造方法赋值
 9     private static Liyuchun liyuchun = new Liyuchun();
10     
11 //    基于接口编程,动态产生代理对象
12     /*
13      *     参数一:loader表示动态代理对象是由哪个类加载器完成的
14         参数二:interfaces表示动态代理对象与目标对象(春哥)有一样的方法,即相当于获取目标对象(即被代理类)的方法
15         参数三:表示动态代理对象的栏截方法,即每次调用目标对象都会执行该invoke()方法(难点)
16 
17     */
18     public Star getProxy() {
19         
20         ClassLoader classLoader = LiyuchunProxy.class.getClassLoader();
21         @SuppressWarnings("unchecked")
22         Class<Liyuchun>[] interfaces = (Class<Liyuchun>[]) liyuchun.getClass().getInterfaces();
23         
24         return  (Star) Proxy.newProxyInstance(
25                 classLoader, //参数一
26                 interfaces , //参数二
27                 new InvocationHandler() { //参数三
28                     
29                     public Object invoke(
30                             Object proxy, 
31                             Method method, //代理类的方法
32                             Object[] args//代理类的参数,第一个参数为args[0],第二个为args[1],以此类推
33                             )throws Throwable 
34                     {
35                         /*System.out.println("方法名:"+method.getName());*/
36                         //System.out.println(method);
37                         if("sing".equals(method.getName())){
38 //                            调用春哥sing方法
39                             String money = (String) args[0];
40                             if(Integer.parseInt(money)>=3){
41                                 method.invoke(liyuchun, money);
42                             }else{
43                                 System.out.println("春哥的出场费不够");
44                             }
45                         }
46                         return null;
47                     }
48                 });
49     }
50 }

 

  4、用户

 1 //    歌迷类
 2 public class Fans  {
 3 
 4     public static void main(String[] args) {
 5 //        创建代理对象
 6         LiyuchunProxy liyuchunProxy = new LiyuchunProxy();
 7 //        通过代理对象找目标对象
 8         Star star = liyuchunProxy.getProxy();
 9 //        业务方法
10         //star.sing();
11         star.sing("3");
12     }
13 }

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2013-04-30 13:38  hacket520  阅读(256)  评论(0编辑  收藏  举报