1. 1. 动态代理
    1. 1.1. cglib动态代理
    2. 1.2. jdk动态代理
    3. 1.3. cglib和jdk区别

动态代理

  • Spring动态代理主要是通过cglib和jdk的动态代理实现.
  • Aspectj是一个单独的AOP框架,在编译或运行时生成代理类,可以实现前置增强、环绕增强、后置增强等功能。平时开发可以引入Aspetcj依赖实现一系列代理操作

cglib动态代理

注意:jdk8以上版本对反射进行了限制,需要手动打开。VM参数添加:–add-opens java.base/java.lang=ALL-UNNAMED

实现原理:

  1. 创建一个被代理类

  2. 新建一个Interceptor实现MethodInterCeptor,重写内部的intercept方法

  3. 使用Enhancer获取代理对象

  1. 创建被代理类:
1
2
3
4
5
6
7
8
9
package com.haomiao.proxy.dynamic.cglib;

public class SmsService {

public void sendMessage() {
System.out.println("send message success");
}
}

  1. 实现Interceptor
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.haomiao.proxy.dynamic.cglib;

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

import java.lang.reflect.Method;

public class DebugInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("proxy start...");
Object object = methodProxy.invokeSuper(o, objects);
System.out.println("proxy end...");
return object;
}
}

  1. 获取代理对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.haomiao.proxy.dynamic.cglib;

import net.sf.cglib.proxy.Enhancer;

public class CglibFactory {

public static Object getProxy(Class<?> clazz) {
// 创建动态代理增强类
Enhancer enhancer = new Enhancer();
enhancer.setClassLoader(clazz.getClassLoader());
enhancer.setSuperclass(clazz);
enhancer.setCallback(new DebugInterceptor());
return enhancer.create();
}

}
  1. 测试
1
2
3
4
5
6
7
8
9
package com.haomiao.proxy.dynamic.cglib;

public class CglibTest {

public static void main(String[] args) {
SmsService proxy = (SmsService) CglibFactory.getProxy(SmsService.class);
proxy.sendMessage();
}
}

jdk动态代理

主要流程:

  1. 创建被代理的接口,实现被代理接口
  2. 创建一个代理类实现InvocationHandler ,重写invoke方法
  3. 使用Proxy.newProxyInstance获取代理对象
  1. 创建被代理的接口
1
2
3
4
5
6
7
package com.haomiao.proxy.dynamic.jdk;

public interface SmsService {

void sendMessage();
}

  1. 实现被代理的接口
1
2
3
4
5
6
7
8
9
package com.haomiao.proxy.dynamic.jdk;

public class SmsServiceImpl implements SmsService {
@Override
public void sendMessage() {
System.out.println("send message");
}
}

  1. 实现InvocationHandler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.haomiao.proxy.dynamic.jdk;

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

public class DebugInvocationHandler implements InvocationHandler {

private final Object target;

public DebugInvocationHandler(Object target) {
this.target = target;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("proxy start...");
Object invoke = method.invoke(target, args);
System.out.println("proxy end...");
return invoke;
}
}

  1. 通过Proxy获取代理对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.haomiao.proxy.dynamic.jdk;

import java.lang.reflect.Proxy;

public class JdkProxyFactory {

public static Object getProxy(Object target) {
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new DebugInvocationHandler(target));
}

}

  1. 测试
1
2
3
4
5
6
7
8
9
10
package com.haomiao.proxy.dynamic.jdk;

public class JdkProxyTest {

public static void main(String[] args) {
SmsService proxy = (SmsService) JdkProxyFactory.getProxy(new SmsServiceImpl());
proxy.sendMessage();
}
}

cglib和jdk区别

  • JDK 动态代理是官方的,它要求被代理的类必须实现接口。它的原理是动态生成一个接口的实现类来作为代理。

  • CGLIB 是第三方的,它不需要接口。它的原理是动态生成一个被代理类的子类来作为代理。但也正因为是继承,所以它不能代理 final 的类,被代理的方法也不能是 finalprivate

  • 就二者的效率来说,大部分情况都是 JDK 动态代理更优秀,随着 JDK 版本的升级,这个优势更加明显。