jdk动态代理和cglib代理demo及总结

本文通过示例对比了JDK动态代理与CGLIB代理技术,详细介绍了两种代理方式的工作原理及其在Spring AOP中的应用。JDK代理基于接口实现,适用于实现了接口的目标对象;而CGLIB代理则通过继承实现,适用于未实现接口的类。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

jdk动态代理和cglib代理技术在框架中使用非常频繁,spring框架的AOP技术就使用二者代理技术进行切面编程,通过了解二者的代理机制来对Aop开发更深的理解。在这我分别对两者代理技术分别做出演示!


jdk动态代理

这里写图片描述
使用jdk动态代理只需要有jdk环境即可,是基于接口的代理技术,因此目标对象必须实现一个接口。
接口类UserService

package com.it.jdkProxy;

public interface UserService {
    void find();
    void get();
    void udpate();
    void delete();
}

目标对象UserServiceImpl

public class UserServiceImpl implements UserService {

    @Override
    public void find() {
        System.out.println("查询用户");
    }
    @Override
    public void get() {
        System.out.println("保存用户");
    }
    @Override
    public void udpate() {
        System.out.println("更新用户");
    }
    @Override
    public void delete() {
        System.out.println("删除用户");
    }
    private void prov(){
        System.out.println("测试private修饰");
    }
    protected void prot(){
        System.out.println("测试protected修饰");
    }
}

代理类UserServiceProxyFactory

package com.itcast.jdkProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class UserServiceProxyFactory implements InvocationHandler{
    private UserServiceImpl target;
    //通过构造传入目标对象
    public UserServiceProxyFactory(UserServiceImpl target) {
        super();
        this.target = target;
    }
    //获取动态代理对象
    public UserService getProxyUserService(){
        return (UserService) Proxy.newProxyInstance(UserServiceProxyFactory.class.getClassLoader(),
                target.getClass().getInterfaces(),
                this);
    }
    //代理对象的增强方法(核心方法)
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //预处理
        System.out.println("开启事务");
        //执行目标对象的方法(对所有public方法)
        Object invoke = method.invoke(target, args);
        //后处理
        System.out.println("提交事务");
        return invoke;
    }
}

测试类TestJdkProxy

package com.itcast.jdkProxy;

import org.junit.Test;

public class TestJdkProxy {
    @Test
    public void test(){
        //创建目标对象
        UserServiceImpl target = new UserServiceImpl();

        long currentTimeMillis1 = System.currentTimeMillis();
        //创建代理工厂
        UserServiceProxyFactory proxyFactory = new UserServiceProxyFactory(target);
        //得到代理对象
        UserService proxyUserService = proxyFactory.getProxyUserService();
        long currentTimeMillis2 = System.currentTimeMillis();
        //测试增强方法
        proxyUserService.find();
        proxyUserService.delete();
        proxyUserService.get();
        proxyUserService.udpate();
        System.out.println(currentTimeMillis2-currentTimeMillis1);
    }
}

测试结果
这里写图片描述

cglib代理

cglib代理是基于继承的代理技术,目标对象必须继承某个类,所以目标类不应该被final修饰
需要导包
这里写图片描述
目标对象UserServiceImpl(与jdk演示的目标对象时同一个)

代理类UserServiceImplProxyFactory

package com.itcast.cglibProxy;

import java.lang.reflect.Method;

import com.itcast.jdkProxy.UserServiceImpl;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class UserServiceImplProxyFactory implements MethodInterceptor{
    //持有要增强的对象
    private UserServiceImpl target;
    //持有增强器(手动创建)
    private Enhancer enhancer = new Enhancer(); 
    //代理对象的get方法
    public UserServiceImpl getProxy(UserServiceImpl target){
        //参数传入要增强的对象
        this.target = target;
        //设置父类
        enhancer.setSuperclass(this.target.getClass());
        enhancer.setCallback(this);
        //通过字节码技术创建实例
        return (UserServiceImpl) enhancer.create();
    }
    /**
     * 所有方法都会被这个方法拦截。该类实现了创建子类的方法与代理的方法。
     * getProxy方法用过参数传入父类的字节码,用过扩展
     * 父类的class来创建代理对象。intercapter方法拦截所有目标类方法的调用,
     * obj代表目标类的实例,method为目标类方法的放射对象
     * ,args为方法的动态参数,proxy为代理类实例
     */
    @Override
    public Object intercept(Object obj, Method method, Object[] arg , MethodProxy methodProxy) 
            throws Throwable {
        System.out.println("cglib实现事务开始");
        Object result = methodProxy.invokeSuper(obj, arg);
        System.out.println("cglib实现事务提交!");

        return result;
    }

}

测试类TestCglibProxy

package com.itcast.cglibProxy;

import java.awt.SystemColor;
import org.junit.Test;
import com.itcast.jdkProxy.UserServiceImpl;

public class TestCglibProxy {
    @Test
    public void test(){
        //创建代理类对象
        UserServiceImplProxyFactory proxyFactory = new UserServiceImplProxyFactory();
        //得到子类实例

        long currentTimeMillis1 = System.currentTimeMillis();
        UserServiceImpl proxy = proxyFactory.getProxy(new UserServiceImpl());
        long currentTimeMillis2 = System.currentTimeMillis();
        //测试增强类的方法
        proxy.find();
        proxy.delete();
        proxy.get();
        proxy.udpate();
        //查看对象创建耗费的时间
        System.out.println("创建对象耗费时间:"+(currentTimeMillis2-currentTimeMillis1));
    }
}

测试结果:
这里写图片描述
总结:
两者的代理方式有区别.
一是jdk代理的目标对象需要实现一个接口,对pojo类没有实现任何接口是不能被代理的,cglib代理需要的目标对象需要继承一个父类,这个条件对于任何类来说都是可以被代理的,因为所有类的父类都是Object类。
二是jdk动态代理创建代理对象耗费时间非常短,大家可以从测试结果上看出,相比较cglib代理很节省时间资源。所以在创键多例对象的代理对象时应该用jdk代理,cglib代理可以用在单例的代理对象创建。
三是动态代理只能对public修饰的方法进行调用,测试中分别写了protected和private方法,并不能调用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值