java代理

代理

概念

         代理模式是對象的結構型模式,代碼模式給某一個對象提供代理,並由代理對象控制原對象(目標對象,被代理對象)的引用。簡單點說,就是經過一個工廠生成一個類的代理對象,當客戶端使用的時候不直接使用目標對象,而是直接使用代理對象。代理對象至關於中介.java

1        Jdk靜態代理

1.1     概念

1.1.1     代理類和目標類實現相同的接口

1.1.2     代理類持有目標類的     的引用

1.2      實例

1.2.1     建立接口

public interface UserService {  web

    public void addUser(String userId,String userName);  spring

}  ide

1.2.2     建立實現類

public class UserServiceImpl implements UserService {測試

    @Overridethis

    public void addUser(String userId, String userName) {spa

       System.out.println("UserServiceImpl addUser userId->>"+userId);.net

    }代理

}對象

1.2.3     建立代理類

(代理類持有被代理類的引用)

public class UserServiceImplProxy implements UserService {

    private UserService userService;

    public UserServiceImplProxy(UserService userService){

       this.userService = userService;

    }

    @Override

    public void addUser(String userId, String userName) {

       try {

           System.out.println("開始執行:addUser");

           userService.addUser(userId, userName);

           System.out.println("addUser執行成功。");

       } catch (Exception e) {

           System.out.println("addUser執行失敗。");

       }

    }

         }

1.2.4     建立測試類

public class Client {

         public static void main(String[] args) {

          UserService userService = new UserServiceImplProxy(new UserServiceImpl());

          userService.addUser("001", "centre");

         }

}

1.2.5     缺點

須要爲每個目標類建立一個代理類,須要創建大量的代理類,耦合度高.違背了重複代碼只寫一次的原則.

 

 

2        Jdk動態代理

2.1     概念

Jdk的動態要求目標對象必須實現接口,由於它建立代理對象的時候是根據接口建立的。若是不實現接口,jdk沒法給目標對象建立代理對象。被代理對象能夠能夠實現多個接口,建立代理時指定建立某個接口的代理對象就能夠調用該接口定義的方法了   

2.1.1     被代理對象必須實現接口,能夠實現多個接口

2.1.2     代理對象由代理工廠生成

2.2     實例

2.2.1   建立接口Service接口和UserService接口(上面的接口)

public interface Service {

      public void sayHello(String name);

}

 

2.2.2     建立目標對象

public class UserServiceImpl implements UserService ,Service{

         @Override

         public void addUser(String userId, String userName) {

                   System.out.println("UserServiceImpl addUser userId->>"+userId);

         }

@Override

         public void sayHello(String name) {

                   System.out.println("你好:"+name);

         }

              }

2.2.3     建立生成代理對象的類

 

public class LogHandler implements InvocationHandler {

         private Object targertObject;

         public Object newInstance(Object targertObject){

                   this.targertObject = targertObject;

                   Class targertClass = targertObject.getClass();

                return  Proxy.newProxyInstance(targertClass.getClassLoader(),

targertClass.getInterfaces(),this);

         }

  @Override

         public Object invoke(Object proxy, Method method, Object[] args)

                            throws Throwable {

                   System.out.println("調用方法"+method.getName());

                   Object ret = null;

                   try {

                            ret = method.invoke(targertObject, args);

                            System.out.print("成功調用方法:"+method.getName()+";參數爲:");

                            for (int i = 0; i < args.length; i++) {

                                     System.out.println(args[i]);

                            }

                   } catch (Exception e) {

                            e.printStackTrace();

                            System.out.print("調用方法:"+method.getName()+"失敗;參數爲:");

                            for (int i = 0; i < args.length; i++) {

                                     System.out.print(args[i]);

                            }

                   }

                   return ret;

         }

}

2.2.4     建立測試類

public class Client {

         public static void main(String[] args) {

                   Service Service = (Service)new LogHandler().newInstance(new UserServiceImpl());

                   UserService userService = (UserService)new LogHandler().newInstance(new UserServiceImpl());

                   userService.addUser("001", "centre");

                   Service.sayHello("centre");

         }

}

2.2.5     缺點

jdk給目標類提供動態要求目標類必須實現接口,當一個目標類不實現接口時,jdk是沒法爲其提供動態代理的

3        Jdk動態代理

3.1     CGLIB動態代理

spring在給某個類提供動態代理時會自動在jdk動態代理和cglib動態代理中動態的選擇。使用cglib爲目標類提供動態代理:須要導入cglib.jar和asm.jar

若是出現asm中的類沒法找到的異常,在java工程中是真的缺乏asm.jar,而在web工程中極可能是asm.jar和spring提供的org.springframework.asm-3.0.4.RELEASE.jar包衝突。

3.1.1    CGLIB動態代理首先編寫一個目標類:UserServiceImpl.java(上面的類)

3.1.2    而後爲其建立一個代理工廠,用於生成目標類的代理對象:CglibProxy.java

若是一個類繼承了某個類,在子類中沒有一個方法,用cglib生成該子類的動態代理類中將沒有一個方法。

3.1.3     編寫CGLIB代理類

public class CglibProxy implements MethodInterceptor{

 

         @Override

         public Object intercept(Object obj, Method method, Object[] args,

                            MethodProxy proxy) throws Throwable {

        System.out.println("調用的方法是:" + method.getName());

        Object ret = null;

        try {

            ret = proxy.invokeSuper(obj, args);

                            System.out.print("成功調用方法:"+method.getName()+";參數爲:");

                            for (int i = 0; i < args.length; i++) {

                                     System.out.print(args[i]);

                            }

                   } catch (Exception e) {

                            e.printStackTrace();

                            System.out.print("調用方法:"+method.getName()+"失敗;參數爲:");

                            for (int i = 0; i < args.length; i++) {

                                     System.out.print(args[i]);

                            }

                   }

                   return ret;

         }

}

3.1.4     編寫測試類

public class CglibClient {

         public static void main(String[] args) {

                   cglibUse1();

         }

         public static void cglibUse1(){

                   Enhancer enhancer = new Enhancer();

 

                   // 設置被代理的類(目標類)

                   enhancer.setSuperclass(UserServiceImpl.class);

                   //使用回調

                   enhancer.setCallback(new CglibProxy());

 

                   // 創造 代理 (動態擴展了UserServiceImpl類)

                   UserServiceImpl my = (UserServiceImpl) enhancer.create();

 

                   //my.addUser("001", "centre");

                   int ret = my.addOperter(15, 22);

                   System.out.println("返回的結果是:"+ret);

         }

}

4         jdk動態和cglib動態代理比較

Jdk動態代理要求被代理的類要實現接口,而cglib不須要,cglib能根據內存中爲其建立子類(代理對象)

5        我的理解

Jdk靜態代理能夠理解爲中介(代理類)知道一切,全部的事情由中介來處理,其餘的類完成本身的功能就行了.

jdk動態代理以接口做爲媒介,利用反射創建起代理類和被代理類的關係.

CGLib的具體還有點沒有理解,但願能夠有人補充.

 

摘自: http://blog.csdn.net/centre10/article/details/6847828

相關文章
相關標籤/搜索