博州住房和城鄉(xiāng)建設(shè)局網(wǎng)站網(wǎng)頁設(shè)計(jì)自學(xué)要多久
jdk動(dòng)態(tài)代理還是cglib代理🧙
- jdk動(dòng)態(tài)代理和cglib代理的示例
- JDK動(dòng)態(tài)代理原理
- CGLIB代理
- final類又沒實(shí)現(xiàn)接口應(yīng)該用哪一種代理, jdk動(dòng)態(tài)代理還是cglib代理
滾滾長(zhǎng)江東逝水,浪花淘盡英雄?!拼鷹罹肌杜R江仙》
jdk動(dòng)態(tài)代理和cglib代理的示例
以下是一個(gè)使用JDK動(dòng)態(tài)代理和CGLIB代理的示例。我們首先創(chuàng)建一個(gè)接口和實(shí)現(xiàn)類,然后分別使用JDK動(dòng)態(tài)代理和CGLIB代理來創(chuàng)建代理對(duì)象。
- 接口:
UserService.java
public interface UserService {void addUser(String name);
}
- 實(shí)現(xiàn)類:
UserServiceImpl.java
public class UserServiceImpl implements UserService {@Overridepublic void addUser(String name) {System.out.println("Adding user: " + name);}
}
- JDK動(dòng)態(tài)代理:
JdkProxyHandler.java
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;public class JdkProxyHandler implements InvocationHandler {private Object target;public JdkProxyHandler(Object target) {this.target = target;}@SuppressWarnings("unchecked")public <T> T getProxyInstance() {return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("JDK Proxy - Before method execution");Object result = method.invoke(target, args);System.out.println("JDK Proxy - After method execution");return result;}
}
- CGLIB代理:
CglibProxyHandler.java
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;public class CglibProxyHandler implements MethodInterceptor {private Object target;public CglibProxyHandler(Object target) {this.target = target;}@SuppressWarnings("unchecked")public <T> T getProxyInstance() {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(target.getClass());enhancer.setCallback(this);return (T) enhancer.create();}@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println("CGLIB Proxy - Before method execution");Object result = proxy.invokeSuper(obj, args);System.out.println("CGLIB Proxy - After method execution");return result;}
}
- 測(cè)試類:
ProxyTest.java
public class ProxyTest {public static void main(String[] args) {UserService userService = new UserServiceImpl();// 使用JDK動(dòng)態(tài)代理JdkProxyHandler jdkProxyHandler = new JdkProxyHandler(userService);UserService jdkProxy = jdkProxyHandler.getProxyInstance();jdkProxy.addUser("John");System.out.println("------------------------------------");// 使用CGLIB代理CglibProxyHandler cglibProxyHandler = new CglibProxyHandler(userService);UserService cglibProxy = cglibProxyHandler.getProxyInstance();cglibProxy.addUser("Jane");}
}
運(yùn)行 ProxyTest.java
,你將看到以下輸出:
JDK Proxy - Before method execution
Adding user: John
JDK Proxy - After method execution
------------------------------------
CGLIB Proxy - Before method execution
Adding user: Jane
CGLIB Proxy - After method execution
JDK動(dòng)態(tài)代理和CGLIB代理都是AOP(面向切面編程)中的實(shí)現(xiàn)技術(shù),它們可以在不修改目標(biāo)類代碼的情況下,為目標(biāo)類添加一些額外的功能。
JDK動(dòng)態(tài)代理原理
JDK動(dòng)態(tài)代理是基于Java反射機(jī)制實(shí)現(xiàn)的。它主要使用了java.lang.reflect.Proxy
類和java.lang.reflect.InvocationHandler
接口。
JDK動(dòng)態(tài)代理的核心思想是:為目標(biāo)類創(chuàng)建一個(gè)代理對(duì)象,這個(gè)代理對(duì)象實(shí)現(xiàn)了目標(biāo)類的接口。當(dāng)代理對(duì)象的方法被調(diào)用時(shí),實(shí)際上是調(diào)用了InvocationHandler
的invoke
方法。在invoke
方法中,我們可以在調(diào)用目標(biāo)類方法之前和之后執(zhí)行一些自定義的邏輯。
要使用JDK動(dòng)態(tài)代理,需要滿足以下條件:
- 目標(biāo)類必須實(shí)現(xiàn)一個(gè)或多個(gè)接口。
- 為目標(biāo)類編寫一個(gè)
InvocationHandler
實(shí)現(xiàn)類。
JDK動(dòng)態(tài)代理的主要局限在于它只能代理實(shí)現(xiàn)了接口的類。如果一個(gè)類沒有實(shí)現(xiàn)接口,就無法使用JDK動(dòng)態(tài)代理。
CGLIB代理
CGLIB(Code Generation Library)是一個(gè)第三方代碼生成庫,它可以在運(yùn)行時(shí)為目標(biāo)類生成一個(gè)子類。CGLIB代理的核心思想是:為目標(biāo)類創(chuàng)建一個(gè)子類,并覆蓋目標(biāo)類的方法。當(dāng)代理類的方法被調(diào)用時(shí),實(shí)際上是調(diào)用了MethodInterceptor
的intercept
方法。在intercept
方法中,我們可以在調(diào)用父類(即目標(biāo)類)方法之前和之后執(zhí)行一些自定義的邏輯。
要使用CGLIB代理,需要滿足以下條件:
- 目標(biāo)類不能是final的,因?yàn)镃GLIB需要生成目標(biāo)類的子類。
- 為目標(biāo)類編寫一個(gè)
MethodInterceptor
實(shí)現(xiàn)類。
CGLIB代理的優(yōu)勢(shì)在于它不要求目標(biāo)類實(shí)現(xiàn)接口,但是由于它是通過創(chuàng)建子類來實(shí)現(xiàn)代理的,所以目標(biāo)類不能是final的。
JDK動(dòng)態(tài)代理基于Java反射機(jī)制,要求目標(biāo)類實(shí)現(xiàn)接口。它創(chuàng)建的代理對(duì)象實(shí)現(xiàn)了目標(biāo)類的接口,并通過
InvocationHandler
來實(shí)現(xiàn)方法攔截。
CGLIB代理基于代碼生成技術(shù),不要求目標(biāo)類實(shí)現(xiàn)接口。它創(chuàng)建的代理對(duì)象是目標(biāo)類的子類,并通過
MethodInterceptor
來實(shí)現(xiàn)方法攔截。
兩者都可以實(shí)現(xiàn)在不修改目標(biāo)類代碼的情況下,為目標(biāo)類添加額外功能。選擇哪種代理方式取決于目標(biāo)類是否實(shí)現(xiàn)了接口以及其他特殊需求。
final類又沒實(shí)現(xiàn)接口應(yīng)該用哪一種代理, jdk動(dòng)態(tài)代理還是cglib代理
如果目標(biāo)類是final類且沒有實(shí)現(xiàn)接口,那么JDK動(dòng)態(tài)代理和CGLIB代理都無法直接對(duì)其進(jìn)行代理。JDK動(dòng)態(tài)代理要求目標(biāo)類實(shí)現(xiàn)一個(gè)或多個(gè)接口,而CGLIB代理需要生成目標(biāo)類的子類,對(duì)于final類是無法創(chuàng)建子類的。
在這種情況下,你可以考慮以下解決方案:
-
修改目標(biāo)類,去除
final
修飾符,或?yàn)槠鋵?shí)現(xiàn)一個(gè)接口。然后,你可以選擇使用JDK動(dòng)態(tài)代理或CGLIB代理。 -
如果不能修改目標(biāo)類,你可以嘗試使用裝飾器模式。創(chuàng)建一個(gè)新類,實(shí)現(xiàn)與目標(biāo)類相同的接口(或擴(kuò)展自目標(biāo)類,如果目標(biāo)類不是final的),并在新類中包裝目標(biāo)類。然后,在新類中實(shí)現(xiàn)代理邏輯。這種方式雖然不能直接代理目標(biāo)類,但仍然可以在不修改目標(biāo)類的情況下,為其添加額外的功能。
請(qǐng)注意,裝飾器模式并非代理模式,但在某些情況下,它可以作為一種替代方案來實(shí)現(xiàn)類似的功能。