SpringAOP底层原理 - JDK 动态代理

回顾一下AOP相关概念
SpringAOP的理解和底层原理


补充

引介(Introduction):特殊的增强,动态为类增加方法
织入(Weaving):将增强加入到目标类的过程,织入分为三种时期

  • 编译器:AspectJ (上文讲过)
  • 类加载
  • 运行期:jdk动态代理(实现接口),CGlib(子类,不能用final)

目标对象(Target):原始对象
代理对象(Proxy):加入了增强的对象,是生成的;
切面(Aspect):切点 + 增强

本文要说的就是在运行期间织入的两种实现方式之 jdk动态代理


什么是代理模式呢?
代理模式有三个角色,分别是

  • 抽象角色:接口
  • 目标角色:实现类
  • 代理角色:实现接口(InvocationHandler),并引用目标角色

代理模式与装饰者模式的区别
类图(结构)基本一样,但目的不同,装饰模式的前提是已经所有的类,并进行组装;
而使用代理模式时,我们不能直接访问目标角色或没有权限访问时,可以使用代理模式

代理模式分为两种

  • 静态代理:需要为每个目标角色,创建一个对应的代理角色;类的数量会急剧膨胀
  • 动态代理:自动为每个目标角色生成对应的代理角色

接下来就是jdk动态代理的具体实现代码:
实现jdk动态代理的前提是所有的目标类都必须要基于一个统一的接口

定义一个统一的接口

package aopstudy.demo.TestAopByJdk;

public interface UserDao {

    int add(int a, int b);

    String update(String id);
}

定义目标对象,实现统一的接口

package aopstudy.demo.TestAopByJdk;


public class UserDaoImp implements UserDao {

    public int add(int a, int b) {
        System.out.println("执行add方法");
        return a + b;
    }

    public String update(String id) {
        System.out.println("执行update方法");
        return id;
    }
}

创建代理角色

//创建的类得需要实现InvocationHandler,并重写invoke()方法
class UserProxy implements InvocationHandler {

    // 创建谁的代理对象,把谁传进来
    // 通过有参数构造方法传入,参数可以UserDaoImp,亦可以用 Object
    private Object obj;

    public UserProxy(Object obj) {
        this.obj = obj;
    }

    //增强的逻辑部分
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //方法之前执行
        // method.getName():当前执行方法的名字, args:当前执行方法传递的参数
        System.out.println("方法之前执行.....方法名:" + method.getName() + "传递的参数:" + Arrays.toString(args));

        //被增强的方法执行
        // method.invoke 俩个参数 (方法名,方法参数)
        Object res = method.invoke(obj, args);

        //方法之后执行
        System.out.println("方法之后执行.....方法名:" + obj);

        return res;
    }
}

编写测试代码

public class JdkProxy {
    public static void main(String[] args) {
        Class[] interfaces = {UserDao.class};
        //目标类必须基于统一的接口
        UserDao userDao = new UserDaoImp();
        //创建接口实现类代理对象中,newProxyInstance有三个参数,ClassLoader类加载器,,interfaces接口类列表,UserProxy代理角色
        UserDao dao = (UserDao) Proxy.newProxyInstance(JdkProxy.class.getClassLoader(), interfaces, new UserProxy(userDao));
        int result = dao.add(1, 2);
        System.out.println(result);
        System.out.println("-----------------------------------------------------");
        String idRes = dao.update("Jdk Proxy");
        System.out.println(idRes);
    }
}

运行结果:

方法之前执行.....方法名:add传递的参数:[1, 2]
执行add方法
方法之后执行.....方法名:aopstudy.demo.TestAopByJdk.UserDaoImp@5e481248
3
-----------------------------------------------------
方法之前执行.....方法名:update传递的参数:[Jdk Proxy]
执行update方法
方法之后执行.....方法名:aopstudy.demo.TestAopByJdk.UserDaoImp@5e481248
Jdk Proxy
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值