动态代理
代理模式
代理模式是一种设计模式,旨在不干涉原核心代码的基础上对原代码的功能进行增强。通常分为动态代理的静态代理两种实现。其中Spring AOP主要就是基于动态代理实现的切面功能。
动态代理(Dynamic Proxy)提供了一个实现方式,使得我们可以在代码中不去实现一个接口,而是在运行时去实现接口对象。动态代理主要是基于反射特性实现的
其中动态代理的实现方式有JDK实现和Cglib框架实现两种方式,二者最大的不同在于JDK实现的代理对象是接口的实现对象,和被代理对象是并列关系;而Cglib实现的代理对象是被代理对象的继承子对象,是继承关系
JDK实现
JDK实现动态代理基于 Proxy
和 InvocationHandler
这两个JDK提供的类
获取代理对象
我们通过静态方法 Proxy.newProxyInstance
获取一个代理对象,其中
1 | public Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) |
- loader传入被代理类的类加载器
- interfaces传入被代理类实现的接口的Class对象,考虑到可能有多个实现接口故传入一个数组
- h传入实现该接口中方法的handler
实现接口
InvocationHandler接口需要实现以下方法:
1 | public Object invoke(Object proxy,Method method,Object[] args) throw Throwable |
- proxy是代理对象
- method是当前被调用方法的反射对象
- args是参数列表
举例来说:
1 | Controller ctrl=new ControllerImpl(); |
Cglib实现
Cglib已经包含在Spring的依赖库内,可以直接调用 org.springframework.cglib.proxy.Enhancer
实现
Cglib实现动态代理基于 Enhancer
类
对于Cglib实现,代理方法除传入InvocationHandler外,也提供了更强大的 MethodInterceptor
,此外,由于Cglib是基于继承的,因此也支持被代理对象不实现对应接口
在Spring AOP中,如果检测到
其中MethodInterceptor要求实现以下接口:
1 | public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { |
- obj是代理对象
- method是当前被调用方法的反射对象
- args是参数列表
- proxy是当前被调用方法的代理方法
- 其中可以通过
proxy.invokeSuper
方法调用该方法的父类实现
- 其中可以通过
和Proxy不同,Enhancer是一个实例对象。在通过Enhancer获取代理对象前,需要先设置参数
1 | Enhancer enhancer=new Enhancer(); |
Comments