Java中的代理分為靜態(tài)代理和動(dòng)態(tài)代理兩種,下面就分別介紹一下這兩種代理在實(shí)現(xiàn)方式和使用場景上的不同之處。
靜態(tài)代理:靜態(tài)代理是指在代碼執(zhí)行前就已經(jīng)確定代理類和被代理類的關(guān)系。這種代理方式需要手動(dòng)創(chuàng)建一個(gè)代理類,代理類需要實(shí)現(xiàn)被代理類的接口,并且持有被代理類對象的引用。在代理類調(diào)用被代理類方法之前或之后,可以做一些增強(qiáng)或攔截操作。例如:
// 定義接口 public interface UserDao { void save(); } // 實(shí)現(xiàn)被代理類 public class UserDaoImpl implements UserDao { public void save() { System.out.println("保存用戶信息"); } } // 實(shí)現(xiàn)代理類 public class UserDaoProxy implements UserDao { private UserDao userDao; public UserDaoProxy(UserDao userDao) { this.userDao = userDao; } public void save() { System.out.println("開始保存用戶信息"); userDao.save(); System.out.println("保存用戶信息完成"); } } // 測試 public class Test { public static void main(String[] args) { UserDao userDao = new UserDaoImpl(); UserDaoProxy proxy = new UserDaoProxy(userDao); proxy.save(); } }
動(dòng)態(tài)代理:動(dòng)態(tài)代理是指在代碼執(zhí)行期間動(dòng)態(tài)生成代理類,不需要手動(dòng)創(chuàng)建。在Java中,動(dòng)態(tài)代理可以通過java.lang.reflect.Proxy類來實(shí)現(xiàn),它可以動(dòng)態(tài)創(chuàng)建實(shí)現(xiàn)一組給定接口的代理類對象。動(dòng)態(tài)代理需要實(shí)現(xiàn)InvocationHandler接口,并在invoke方法中實(shí)現(xiàn)對目標(biāo)方法的增強(qiáng)或攔截操作。例如:
// 定義接口 public interface UserDao { void save(); } // 實(shí)現(xiàn)被代理類 public class UserDaoImpl implements UserDao { public void save() { System.out.println("保存用戶信息"); } } // 實(shí)現(xiàn)InvocationHandler接口 public class UserDaoHandler implements InvocationHandler { private Object target; public UserDaoHandler(Object target) { this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("開始保存用戶信息"); Object result = method.invoke(target, args); System.out.println("保存用戶信息完成"); return result; } } // 測試 public class Test { public static void main(String[] args) { UserDao userDao = new UserDaoImpl(); UserDao proxy = (UserDao) Proxy.newProxyInstance(UserDao.class.getClassLoader(), new Class[]{UserDao.class}, new UserDaoHandler(userDao)); proxy.save(); } }
總結(jié):靜態(tài)代理需要手動(dòng)編寫代理類,靈活性較低,但相對簡單易懂;動(dòng)態(tài)代理在代碼執(zhí)行期間動(dòng)態(tài)生成代理類,具有較高的靈活性,但相對較復(fù)雜。在實(shí)際應(yīng)用中,如果只需要代理一個(gè)類或一組類,并且代理邏輯較為簡單,則可以使用靜態(tài)代理;如果需要代理多個(gè)類或一組類,并且代理邏輯相對復(fù)雜,則可以考慮使用動(dòng)態(tài)代理。