Spring动态代理

本文深入解析Java动态代理机制,包括基于接口的JDK动态代理和基于类的CGLIB动态代理。介绍了动态代理的实现原理及步骤,并通过具体示例展示了如何在实际应用中运用动态代理。

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

1.  动态代理

动态代理:在程序运行时,运用反射机制动态创建而成。

1、 动态代理和静态代理的角色是一样的。

2、 动态代理的代理类是动态生成的。

3、 分为两类一类基于接口动态代理和基于类的动态代理。

a)    基于接口动态代理---jdk动态代理

                i.         Java动态代理使用Proxy类和InvocationHandler接口。

               ii.         使用Proxy类做代理的时候,必须有InvocationHandler对象。

public static Object newProxyInstance(ClassLoader loader,

                                      Class<?>[] interfaces,

                                      InvocationHandler h)

                               throws IllegalArgumentException

 

loader - 定义代理类的类加载器

interfaces - 代理类要实现的接口列表

h - 指派方法调用的调用处理程序

Object: 因为不能确定要代理的对象是什么类型,所以要返回类的祖先!

是谁创建的动态代理?

InvocationHandler:

invoke(Object proxy, Method method, Object[] args)

Object invoke(Object proxy,

              Method method,

              Object[] args)

              throws Throwable

proxy - 在其上调用方法的代理实例

 

method - 对应于在代理实例上调用的接口方法的 Method 实例。Method 对象的声明类将是在其中声明方法的接口,该接口可以是代理类赖以继承方法的代理接口的超接口。

 

args - 包含传入代理实例上方法调用的参数值的对象数组,如果接口方法不使用参数,则为 null。基本类型的参数被包装在适当基本包装器类(如 java.lang.Integer 或 java.lang.Boolean)的实例中。

利用静态代理中的例子来解释:

Proxy: 中介UserProxy

Method:rent()方法

Args:参数:null

b)    基于类的动态代理---cglib

                i.         对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。

案例:使用动态代理,在每个方法执行前,添加一句话【方法被执行了】。

1、在UserDao接口中层创建四个方法:CRUD

2、在UserDaoImpl类中实现四个方法:CRUD
3、创建一个代理类实现InvocationHandler接口中的invoke方法。

动态代理实现步骤:

1、 创建一个类来实现InvocationHandler接口。实现invoke方法()

a)    Invoke方法中就是具体的你要实现的功能!

                i.         输出我们的“方法被执行了!”

2、 在该接口中创建动态代理。Proxy. newProxyInstance(参数1,参数2,参数3);

3、 测试!

代码:

public interface UserDao {

    void add();

    void delete();

    void update();

    void search();

    String show();

}

 

 

public class UserDaoImpl implements UserDao {

 

    @Override

    public void add() {

        System.out.println("添加用户");

    }

    @Override

    public void delete() {

        System.out.println("删除用户");

    }

 

    @Override

    public void update() {

        System.out.println("更新用户");

    }

 

    @Override

    public void search() {

        System.out.println("查询用户");

    }

    @Override

    public String show() {

        return "show";

    }

}

 

public class UserDaoProxy implements InvocationHandler {

    // 声明要代理的对象

    private Object object;

 

    public Object getObject() {

        return object;

    }

 

    // 给代理对象赋值

    public void setObject(Object object) {

        this.object = object;

    }

 

    // 如何创建一个代理对象?使用Proxy类来创建

    public Object getProxy() {

        // 第一个参数是类加载器,第二个参数是代理对象的接口,第三个是InvocationHandler 对象

        return Proxy.newProxyInstance(this.getClass().getClassLoader(), object.getClass().getInterfaces(), this);

    }

 

    /**

     * proxy 代理的对象 method 代理对象的方法 args 参数数组

     */

   

    @Override

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        txStart();

        // obj:被代理的对象!args:参数数组,说白了。 method.invoke(object, args) 就是执行真是代理对象的方法。

        Object obj = method.invoke(object, args);

        System.out.println(obj+"==========");

        txClose();

        return obj;

    }

 

    public void txStart() {

        System.out.println("开启事务!");

    }

   

    public void txClose() {

        System.out.println("关闭事务!");

    }

 

}

测试:

public class Test {

    public static void main(String[] args) {

        // 创建代理对象

        UserDaoProxy u = new UserDaoProxy();

        // 创建代理对象 ,说明你要代理的那个类

        UserDao ud = new UserDaoImpl();

        u.setObject(ud);

        // 得到代理对象!

        UserDao userDao = (UserDao) u.getProxy();

        // 代理类的方法被执行的时候,则会调用InvocationHandler中的invoke方法。

        userDao.add();

        userDao.delete();

        userDao.search();

        userDao.show();

 

    }

}

能否将租房改成动态代理。

注意:InvocationHandler 的invoke、方法 和 method.invoke方法不一样!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值