Spring框架在實現動態代理時,提供了兩種選擇:基于JDK的動態代理和基于CgLib的動態代理。
JDK動態代理只能代理實現了接口的類,而CgLib動態代理可以代理沒有實現接口的類。因此,如果需要代理的類實現了接口,建議使用JDK動態代理;如果需要代理的類沒有實現接口,或者需要對類的方法進行代理而不是接口的方法,建議使用CgLib動態代理。
另外,由于JDK動態代理是基于接口的,因此它的代理效率比CgLib動態代理要高。在大多數情況下,建議首選JDK動態代理,只有在必要的情況下才考慮使用CgLib動態代理。
需要注意的是,如果需要代理的類已經是final類,則無法使用CgLib動態代理代理該類。此外,CgLib動態代理也可能會影響應用程序的性能,因此在使用CgLib動態代理時,需要謹慎評估其對性能的影響。
下面是使用Spring基于JDK和CgLib動態代理的示例代碼。
假設我們有一個接口UserService和一個實現類UserServiceImpl,代碼如下:
public?interface?UserService?{????void?addUser();}public?class?UserServiceImpl?implements?UserService?{????@Override????public?void?addUser()?{????????System.out.println("Add?user.");????}}
現在我們想要在調用UserServiceImpl的addUser()方法之前和之后執行一些額外的邏輯。我們可以使用Spring的動態代理功能來實現這一點。
基于JDK的動態代理示例代碼如下:
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的動態代理示例代碼如下:
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();????}}
以上兩個示例代碼中,我們都定義了一個代理類,并實現了InvocationHandler或MethodInterceptor接口來處理方法調用。在main方法中,我們通過Proxy.newProxyInstance()或Enhancer.create()方法來創建代理對象,并調用其方法,此時代理對象會自動調用我們定義的invoke()或intercept()方法來執行相應的邏輯。
Copyright ? 2013-2021 河南云和數據信息技術有限公司 豫ICP備14003305號 ISP經營許可證:豫B-20160281