日本国产欧美大码A视频 _国产高颜值极品在线视频_色偷偷亚洲第一综合网_国产精品一二三社区视频_久久久青草视频

IT培訓(xùn)-高端面授IT培訓(xùn)機(jī)構(gòu)
云和教育:云和數(shù)據(jù)集團(tuán)高端IT職業(yè)教育品牌
  • 國(guó)家級(jí)
    全民數(shù)字素養(yǎng)與技能培訓(xùn)基地
  • 河南省
    第一批產(chǎn)教融合型企業(yè)建設(shè)培育單位
  • 鄭州市
    數(shù)字技能人才(碼農(nóng))培養(yǎng)評(píng)價(jià)聯(lián)盟
當(dāng)前位置:
首頁(yè)IT問(wèn)答正文

Spring對(duì)JDK和CgLib動(dòng)態(tài)代理該怎么選?

  • 發(fā)布時(shí)間:
    2023-03-21
  • 版權(quán)所有:
    云和教育
  • 分享:

Spring框架在實(shí)現(xiàn)動(dòng)態(tài)代理時(shí),提供了兩種選擇:基于JDK的動(dòng)態(tài)代理和基于CgLib的動(dòng)態(tài)代理。

JDK動(dòng)態(tài)代理只能代理實(shí)現(xiàn)了接口的類(lèi),而CgLib動(dòng)態(tài)代理可以代理沒(méi)有實(shí)現(xiàn)接口的類(lèi)。因此,如果需要代理的類(lèi)實(shí)現(xiàn)了接口,建議使用JDK動(dòng)態(tài)代理;如果需要代理的類(lèi)沒(méi)有實(shí)現(xiàn)接口,或者需要對(duì)類(lèi)的方法進(jìn)行代理而不是接口的方法,建議使用CgLib動(dòng)態(tài)代理。

另外,由于JDK動(dòng)態(tài)代理是基于接口的,因此它的代理效率比CgLib動(dòng)態(tài)代理要高。在大多數(shù)情況下,建議首選JDK動(dòng)態(tài)代理,只有在必要的情況下才考慮使用CgLib動(dòng)態(tài)代理。

需要注意的是,如果需要代理的類(lèi)已經(jīng)是final類(lèi),則無(wú)法使用CgLib動(dòng)態(tài)代理代理該類(lèi)。此外,CgLib動(dòng)態(tài)代理也可能會(huì)影響應(yīng)用程序的性能,因此在使用CgLib動(dòng)態(tài)代理時(shí),需要謹(jǐn)慎評(píng)估其對(duì)性能的影響。

下面是使用Spring基于JDK和CgLib動(dòng)態(tài)代理的示例代碼。

假設(shè)我們有一個(gè)接口UserService和一個(gè)實(shí)現(xiàn)類(lèi)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的動(dòng)態(tài)代理功能來(lái)實(shí)現(xiàn)這一點(diǎn)。

基于JDK的動(dòng)態(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的動(dòng)態(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();
    }
}

以上兩個(gè)示例代碼中,我們都定義了一個(gè)代理類(lèi),并實(shí)現(xiàn)了InvocationHandler或MethodInterceptor接口來(lái)處理方法調(diào)用。在main方法中,我們通過(guò)Proxy.newProxyInstance()或Enhancer.create()方法來(lái)創(chuàng)建代理對(duì)象,并調(diào)用其方法,此時(shí)代理對(duì)象會(huì)自動(dòng)調(diào)用我們定義的invoke()或intercept()方法來(lái)執(zhí)行相應(yīng)的邏輯。