更新時間:2023年03月20日10時01分 來源:傳智教育 瀏覽次數(shù):
Spring框架在實現(xiàn)動態(tài)代理時,提供了兩種選擇:基于JDK的動態(tài)代理和基于CgLib的動態(tài)代理。
JDK動態(tài)代理只能代理實現(xiàn)了接口的類,而CgLib動態(tài)代理可以代理沒有實現(xiàn)接口的類。因此,如果需要代理的類實現(xiàn)了接口,建議使用JDK動態(tài)代理;如果需要代理的類沒有實現(xiàn)接口,或者需要對類的方法進(jìn)行代理而不是接口的方法,建議使用CgLib動態(tài)代理。
另外,由于JDK動態(tài)代理是基于接口的,因此它的代理效率比CgLib動態(tài)代理要高。在大多數(shù)情況下,建議首選JDK動態(tài)代理,只有在必要的情況下才考慮使用CgLib動態(tài)代理。
需要注意的是,如果需要代理的類已經(jīng)是final類,則無法使用CgLib動態(tài)代理代理該類。此外,CgLib動態(tài)代理也可能會影響應(yīng)用程序的性能,因此在使用CgLib動態(tài)代理時,需要謹(jǐn)慎評估其對性能的影響。
下面是使用Spring基于JDK和CgLib動態(tài)代理的示例代碼。
假設(shè)我們有一個接口UserService和一個實現(xiàn)類UserServiceImpl,代碼如下:
public interface UserService { void addUser(); } public class UserServiceImpl implements UserService { @Override public void addUser() { System.out.println("Add user."); } }
現(xiàn)在我們想要在調(diào)用UserServiceImpl的addUser()方法之前和之后執(zhí)行一些額外的邏輯。我們可以使用Spring的動態(tài)代理功能來實現(xiàn)這一點。
基于JDK的動態(tài)代理示例代碼如下:
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class UserServiceProxy implements InvocationHandler { private UserService userService; public UserServiceProxy(UserService userService) { this.userService = userService; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("Before addUser."); Object result = method.invoke(userService, args); System.out.println("After addUser."); return result; } public static void main(String[] args) { UserService userService = new UserServiceImpl(); InvocationHandler handler = new UserServiceProxy(userService); UserService userServiceProxy = (UserService) Proxy.newProxyInstance( userService.getClass().getClassLoader(), userService.getClass().getInterfaces(), handler ); userServiceProxy.addUser(); } }
基于CgLib的動態(tài)代理示例代碼如下:
import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import net.sf.cglib.proxy.Enhancer; public class UserServiceCgLibProxy implements MethodInterceptor { private UserService userService; public UserServiceCgLibProxy(UserService userService) { this.userService = userService; } @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("Before addUser."); Object result = proxy.invoke(userService, args); System.out.println("After addUser."); return result; } public static void main(String[] args) { UserService userService = new UserServiceImpl(); Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(userService.getClass()); enhancer.setCallback(new UserServiceCgLibProxy(userService)); UserService userServiceProxy = (UserService) enhancer.create(); userServiceProxy.addUser(); } }
以上兩個示例代碼中,我們都定義了一個代理類,并實現(xiàn)了InvocationHandler或MethodInterceptor接口來處理方法調(diào)用。在main方法中,我們通過Proxy.newProxyInstance()或Enhancer.create()方法來創(chuàng)建代理對象,并調(diào)用其方法,此時代理對象會自動調(diào)用我們定義的invoke()或intercept()方法來執(zhí)行相應(yīng)的邏輯。