靜態代理:自己定義的代理類;
動態代理:程序在運行時生成。
一、靜態代理:
接口:UserManager:對用戶的增刪改查。
1 package com.dwr.spring.proxy; 2 3 public interface UserManager { 4 public void addUser(String username,String password); 5 public void deleteUser(int userid); 6 public void modifyUser(int userid,String username,String password); 7 public void findUser(int userid); 8 }
實現類:UserManagerImpl:
1 package com.dwr.spring.proxy; 2 3 public class UserManagerImpl implements UserManager { 4 @Override 5 public void addUser(String username, String password) { 6 System.out.println("--------UserManagerImpl.addUser()----------"); 7 } 8 9 @Override 10 public void deleteUser(int userid) { 11 System.out.println("--------UserManagerImpl.deleteUser()----------"); 12 } 13 14 @Override 15 public void modifyUser(int userid, String username, String password) { 16 System.out.println("--------UserManagerImpl.modifyUser()----------"); 17 } 18 19 @Override 20 public void findUser(int userid) { 21 System.out.println("--------UserManagerImpl.findUser()----------"); 22 }
客戶端類:調用方法;
1 package com.dwr.spring.proxy; 2 3 public class Client { 4 5 public static void main(String[] args){ 6 UserManager userManager = new UserManagerImpl(); 7 userManager.addUser("Jack","123456"); 8 } 9 }
結果:
1 --------UserManagerImpl.addUser()----------
結果正常顯示。
在UserManagerImpl中加入安全性檢測:
1 public void checkSecurity(){ 2 System.out.println("--------UserManagerImpl.checkSecurity()----------"); 3 }
UserManagerImpl中每個方法都要調用該方法,耦合度提高。使用代理實現類實現該功能:
在代理中:必須要有要控制對象的引用;
將安全檢測方法放到代理類中。調用每個方法前進行安全檢測,對原有的類的結構並沒有破壞,也完成了需求。
UserManagerImplProxy類:
1 package com.dwr.spring.proxy; 2 3 public class UserManagerImplProxy implements UserManager { 4 private UserManager userManager; 5 6 public UserManagerImplProxy(UserManager userManager){ 7 this.userManager = userManager; 8 } 9 10 public void checkSecurity(){ 11 System.out.println("--------UserManagerImpl.checkSecurity()----------"); 12 } 13 14 @Override 15 public void addUser(String username, String password) { 16 checkSecurity(); 17 this.userManager.addUser(username,password); 18 } 19 20 @Override 21 public void deleteUser(int userid) { 22 checkSecurity(); 23 this.userManager.deleteUser(userid); 24 } 25 26 @Override 27 public void modifyUser(int userid, String username, String password) { 28 checkSecurity(); 29 this.userManager.modifyUser(userid,username,password); 30 } 31 32 @Override 33 public void findUser(int userid) { 34 checkSecurity(); 35 this.userManager.findUser(userid); 36 } 37 }
客戶端測試:
1 package com.dwr.spring.proxy; 2 3 public class Client { 4 5 public static void main(String[] args){ 6 //使用靜態代理模式實現 7 UserManager userManager = new UserManagerImplProxy(new UserManagerImpl()); 8 userManager.addUser("Jack","123456"); 9 } 10 }
靜態代理模式使我們自己寫的,若接口中方法很多,就會很麻煩,這時就需采用AOP來處理!!!
二、動態代理:
既然是動態代理模式就不需要UserManagerImplProxy這個代理類了。
需要聲明一個類實現InvocationHandler接口,並定義一個newProxy的方法返回動態代理
1 package com.dwr.spring.proxy; 2 3 import java.lang.reflect.InvocationHandler; 4 import java.lang.reflect.Method; 5 import java.lang.reflect.Proxy; 6 7 public class SecurityHandler implements InvocationHandler { 8 private Object targetObject; 9 10 public Object newProxy(Object targetObject){ 11 this.targetObject = targetObject; 12 //返回動態代理 13 return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),targetObject.getClass().getInterfaces(),this); 14 } 15 16 17 public void checkSecurity(){ 18 System.out.println("--------UserManagerImpl.checkSecurity()----------"); 19 } 20 21 @Override 22 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 23 checkSecurity(); 24 Object ret = null; 25 26 try { 27 //調用目標對象的真實方法,將返回值保存在ret中 28 ret = method.invoke(this.targetObject, args); 29 } catch (Exception e){ 30 e.printStackTrace(); 31 } 32 return ret; 33 } 34 }
客戶端測試:
1 SecurityHandler securityHandler = new SecurityHandler(); 2 UserManager userManager = (UserManager) securityHandler.newProxy(new UserManagerImpl()); //創建代理對象 3 userManager.addUser("Tom","123456");
結果:
1 --------UserManagerImpl.checkSecurity()---------- 2 --------UserManagerImpl.addUser()----------
使用動態代理想進行安全檢測就進行安全檢測;不想檢測就不檢測,就是這麼任性。。。
客戶端:
1 package com.dwr.spring.proxy; 2 3 public class Client { 4 5 public static void main(String[] args){ 6 SecurityHandler securityHandler = new SecurityHandler(); 7 UserManager userManager = (UserManager) securityHandler.newProxy(new UserManagerImpl());//進行了安全檢測 8 userManager.addUser("Tom","123456"); 9 System.out.println("++++++++++++++++++++++++++++++++++++++++++++++++++"); 10 UserManager userManager1 = new UserManagerImpl(); //沒有進行安全檢測 11 userManager1.addUser("Lily","123456"); 12 } 13 }
結果:
--------UserManagerImpl.checkSecurity()----------
--------UserManagerImpl.addUser()----------
++++++++++++++++++++++++++++++++++++++++++++++++++
--------UserManagerImpl.addUser()----------
使用CGLib實現:
創建一個類實現MethodInterceptor接口,重寫intercept方法:當代理對象的方法被調用時會調用該方法!!
CGlibProxyFactory類:
1 package com.dwr.spring.proxy; 2 3 import org.springframework.cglib.proxy.Enhancer; 4 import org.springframework.cglib.proxy.MethodInterceptor; 5 import org.springframework.cglib.proxy.MethodProxy; 6 7 import java.lang.reflect.Method; 8 9 public class CGlibProxyFactory implements MethodInterceptor { 10 11 private Object targetObject; 12 13 public Object newProxy(Object targetObject){ 14 this.targetObject = targetObject; 15 Enhancer enhancer = new Enhancer(); 16 enhancer.setSuperclass(this.targetObject.getClass()); 17 enhancer.setCallback(this); 18 //返回代理對象 19 return enhancer.create(); 20 } 21 22 public void checkSecurity(){ 23 System.out.println("--------UserManagerImpl.checkSecurity()----------"); 24 } 25 26 /** 27 * @param proxy 帶來的對象本身 28 * @param method 被攔截到的方法 29 * @param objects 方法的參數 30 * @param methodProxy 方法的代理對象 31 */ 32 @Override 33 public Object intercept(Object proxy, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { 34 checkSecurity(); 35 Object ret = null; 36 37 try { 38 ret = method.invoke(this.targetObject, objects); 39 } catch (Exception e){ 40 e.printStackTrace(); 41 } 42 return ret; 43 } 44 }
測試:
1 package com.dwr.spring.proxy; 2 3 public class CGlibProxyTest { 4 5 public static void main(String[] args){ 6 CGlibProxyFactory factory = new CGlibProxyFactory(); 7 UserManagerImpl userManager = (UserManagerImpl) factory.newProxy(new UserManagerImpl()); 8 userManager.addUser("Tom","123456"); 9 } 10 }
結果:
--------UserManagerImpl.checkSecurity()----------
--------UserManagerImpl.addUser()----------