Java 中有一種稱為動態代理的技術,它可以讓我們在運行時動態地創建代理對象。這個技術對于實現切面編程非常有用。
public interface UserService { public void addUser(String userId, String userName); public void deleteUser(String userId); }
例子中的 UserService 是一個接口,它有兩個方法:addUser 和 deleteUser。如果我們在方法執行前/后打印日志或者統計方法的運行時間,我們可以使用 AOP(Aspect Oriented Programming)來實現。在這個過程中,動態代理就可以派上用場.
public class MyAdvice implements InvocationHandler { private Object target; public MyAdvice(Object target) { this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("--- Before ---"); Object returnValue = method.invoke(target, args); System.out.println("--- After ---"); return returnValue; } }
在這個例子中,我們創建了一個代理對象來實現 UserService 接口。MyAdvice 類實現了 InvocationHandler 接口,這意味著我們必須實現它的 invoke() 方法。在 invoke() 方法中,我們首先打印了一個日志消息,然后調用了目標對象的方法。最后,我們又打印了一個日志消息。我們通過反射調用目標對象的方法,這就意味著代理對象和目標對象必須有相同的接口。因此,我們在 MyAdvice 類的構造函數中傳入了一個實現了 UserService 接口的對象。
public class Main { public static void main(String[] args) { UserService userService = new UserServiceImpl(); MyAdvice myAdvice = new MyAdvice(userService); UserService userServiceProxy = (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(), userService.getClass().getInterfaces(), myAdvice); userServiceProxy.addUser("001", "Tom"); userServiceProxy.deleteUser("001"); } }
在 Main 類的 main() 方法中,我們創建了一個 UserServiceImpl 的實例對象 userService。接下來,我們創建了一個 MyAdvice 的實例對象 myAdvice,并傳入 userService。現在,我們就可以創建代理對象了。我們使用了一個叫做 Proxy 的類來實現動態代理。Proxy 這個類提供了一個靜態方法 newProxyInstance() 來創建代理對象。在這個例子中,我們傳入了 UserServiceImpl 類加載器和 UserService 接口。我們還傳入了我們自己寫的 MyAdvice 類。我們在代理對象上調用了 addUser 和 deleteUser 方法。
Java 的動態代理機制使得 AOP 編程實現起來更加方便。我們可以非常輕松地使用動態代理來打印日志、處理異常等等。同時,我們也不用關心代理對象的實現,這是非常方便的。