参考

https://blog.csdn.net/lan12334321234/article/details/70048780

基于接口代理「JDK」

基于 JDK 实现动态代理,通过 jdk 提供的工具方法 Proxy.newProxyInstance 动态构建全新的代理类 (继承 Proxy 类,并持有 InvocationHandler 接口引用) 字节码文件并实例化对象返回。(jdk 动态代理是由 java 内部的反射机制来实例化代理对象,并代理的调用委托类方法)

缺点:代理的类必须实现接口,如果没有实现接口,则不能使用 JDK 代理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

interface BookInterface {

void addBook();

void intercept();
};

public class BookImpl implements BookInterface {

public void addBook() {
System.out.println("dynamic@BookImpl#addBook");
}

public void intercept() {
System.out.println("dynamic@BookImpl#intercept is intercepted...");
}
// 测试方法
public static void main(String[] args) {
BookProxy proxy = new BookProxy();
BookInterface impl = (BookInterface) proxy.getInstance(new BookImpl());
impl.intercept();
}
};

/**
*
* @projectName:ActiveMq
* @packageName: activeMQ.topicMessage
* @ClassName : BookProxy
* @createBy :Test
* @createDate :2013-2-24下午01:23:25
* @useFor :
*
*/
class BookProxy implements InvocationHandler {
/**
* 委托类
*/
private Object target;

public Object getInstance(Object target) {
this.target = target;

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

public Object invoke(Object obj, Method method, Object[] args)
throws Throwable {
System.out.println("Before Advice");

if ("intercept".equals(method.getName())) {
System.out.println("intercept method is intercepted");

return null;
}
// 注意此处的参数是注入的target 而不是obj
Object result = method.invoke(target, args);
System.out.println("After Advice");
return result;
}

}

Cglib 动态代理「生成子类」

cglib 是针对类来实现代理的,他的原理是对指定的目标类生成一个子类, 并覆盖其中方法实现增强,但因为采用的是继承,所以不能对 final 修饰的类进行代理。cglib 动态代理底层则是借助 asm 来实现的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import java.lang.reflect.Method;

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

public class BookClass {
/**
* 业务方法 使用cglib则不需要额外定义接口 Description: <br>
*
* @see
*/
public void addBook() {
System.out.println("cglib@BookClass#addBook");
}
// 测试
public static void main(String[] args) {
BookProxy proxy = new BookProxy();
BookClass bc = (BookClass) proxy.getInstance(new BookClass());
bc.addBook();
}
};

/**
*
* @projectName:ActiveMq
* @packageName: activeMQ.topicMessage
* @ClassName : BookProxy
* @createBy :Test
* @createDate :2013-2-24下午01:31:22
* @useFor : Cglib 动态代理类 类代理
*
*/
class BookProxy implements MethodInterceptor {
/**
* 委托类
*/
private Object target;

public Object getInstance(Object target) {
this.target = target;
Enhancer en = new Enhancer();
en.setSuperclass(target.getClass());
en.setCallback(this);
return en.create();
}

public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
System.out.println("Before Advice");

// 注意此处的参数是注入的target 而不是obj
Object result = proxy.invoke(target, args);
System.out.println("After Advice");
return result;
}
}

基于 Aspectj 实现动态代理「编译时插入」

修改目标类的字节,织入代理的字节,在程序编译的时候 插入动态代理的字节码,不会生成全新的 Class

基于 instrumentation 实现动态代理「类装载时插入」

修改目标类的字节码、类装载的时候动态拦截去修改,基于 javaagent) -javaagent:spring-instrument-4.3.8.RELEASE.jar (类装载的时候 插入动态代理的字节码,不会生成全新的 Class