总结摘要
Spring AOP Aspect 前置知识 Java动态代理
Java 动态代理
基于JDK实现动态代理
基于JDK来实现动态代理主要用到了java.lang.reflect.InvocationHandler接口和java.lang.reflect.Proxy类。
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
| {
public static void main(String[] args) {
testJdkProxy();
}
/**
* log start time [Tue Oct 07 16:09:48 CST 2025]
* 查询 selectById
* log end time [Tue Oct 07 16:09:48 CST 2025]
* log start time [Tue Oct 07 16:09:48 CST 2025]
* 更新 update
* log end time [Tue Oct 07 16:09:48 CST 2025]
*/
public static void testJdkProxy() {
UserServiceImpl userServiceImpl = new UserServiceImpl();
ClassLoader classLoader = userServiceImpl.getClass().getClassLoader();
Class<?>[] interfaces = userServiceImpl.getClass().getInterfaces();
java.lang.reflect.InvocationHandler logHandler = new LogHandler(userServiceImpl);
UserService proxy = (UserService) java.lang.reflect.Proxy.newProxyInstance(classLoader, interfaces, logHandler);
// 调用代理的方法
proxy.select();
proxy.update();
}
}
interface UserService {
void select();
void update();
}
class UserServiceImpl implements UserService {
public void select() {
System.out.println("查询 selectById");
}
public void update() {
System.out.println("更新 update");
}
}
class LogHandler implements java.lang.reflect.InvocationHandler {
Object target; // 被代理的对象,实际的方法执行者
public LogHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, java.lang.reflect.Method method, Object[] args) throws Throwable {
before();
Object result = method.invoke(target, args);
after();
return result;
}
private void before() {
System.out.println(String.format("log start time [%s] ", new Date()));
}
private void after() {
System.out.println(String.format("log end time [%s] ", new Date()));
}
}
|
动态代理类具有哪些方法,只跟接口有关,跟原始类没有任何关系。这也是基于JDK实现的动态代理,要求原始类必须有接口定义才行的原因。
静态代理类的类名是程序员指定的,动态代理类的类名是自动生成的。动态代理类的类名由2部分构成:$Proxy+自增编号。比如,如果项目中使用Proxy类生成了两个动态代理类,那么,它们的名称就分别为:$Proxy0、$Proxy1。
基于CGLIB实现动态代理
基于CGLIB实现动态代理,需要用到一个核心接口MethodInterceptor和一个核心类Enhancer,它们的用法跟JDK中的InvocationHandler接口和Proxy类相似。
实际上,为了优化性能,CGLIB可以不使用Java反射来执行方法,如下代码所示。MethodProxy的invokeSuper()方法底层依赖CGLIB自己实现的反射(即net.sf.cglib.reflect.FastClass)来执行方法。不过,即便如此,两种动态代理实现方式的性能仍然相差无几。
原生 Cglib
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
| {
public static void main(String[] args) {
testCglibNative();
}
/**
* log start time [Tue Oct 07 15:36:32 CST 2025]
* UserDao 更新 update
* log end time [Tue Oct 07 15:36:32 CST 2025]
* log start time [Tue Oct 07 15:36:32 CST 2025]
* UserDao 查询 selectById
* log end time [Tue Oct 07 15:36:32 CST 2025]
*/
public static void testCglibNative() {
LogInterceptorCglibNative daoProxy = new LogInterceptorCglibNative();
net.sf.cglib.proxy.Enhancer enhancer = new net.sf.cglib.proxy.Enhancer();
enhancer.setSuperclass(UserDao.class); // 设置超类,cglib是通过继承来实现的
enhancer.setCallback(daoProxy);
UserDao dao = (UserDao)enhancer.create(); // 创建代理类
dao.update();
dao.select();
}
}
class UserDao {
public void select() {
System.out.println("UserDao 查询 selectById");
}
public void update() {
System.out.println("UserDao 更新 update");
}
}
class LogInterceptorCglibNative implements net.sf.cglib.proxy.MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, net.sf.cglib.proxy.MethodProxy methodProxy) throws Throwable {
before();
Object result = methodProxy.invokeSuper(o, objects);
after();
return result;
}
private void before() {
System.out.println(String.format("log start time [%s] ", new Date()));
}
private void after() {
System.out.println(String.format("log end time [%s] ", new Date()));
}
}
|
使用CGLIB需要先在项目中引入CGLIB包,Maven配置如下所示。
1
2
3
4
5
6
| <!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
|
Spring Cglib
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
| {
public static void main(String[] args) {
testCglibSpring();
}
/**
* log start time [Tue Oct 07 15:39:04 CST 2025]
* UserDao 更新 update
* log end time [Tue Oct 07 15:39:04 CST 2025]
* log start time [Tue Oct 07 15:39:04 CST 2025]
* UserDao 查询 selectById
* log end time [Tue Oct 07 15:39:04 CST 2025]
*/
public static void testCglibSpring() {
LogInterceptorCglibSpring daoProxy = new LogInterceptorCglibSpring();
org.springframework.cglib.proxy.Enhancer enhancer = new org.springframework.cglib.proxy.Enhancer();
enhancer.setSuperclass(UserDao.class); // 设置超类,cglib是通过继承来实现的
enhancer.setCallback(daoProxy);
UserDao dao = (UserDao)enhancer.create(); // 创建代理类
dao.update();
dao.select();
}
}
class UserDao {
public void select() {
System.out.println("UserDao 查询 selectById");
}
public void update() {
System.out.println("UserDao 更新 update");
}
}
class LogInterceptorCglibSpring implements org.springframework.cglib.proxy.MethodInterceptor {
@Override
public Object intercept(Object object, java.lang.reflect.Method method, Object[] objects, org.springframework.cglib.proxy.MethodProxy methodProxy) throws Throwable {
before();
// 注意这里是调用 invokeSuper 而不是 invoke,否则死循环,methodProxy.invokesuper执行的是原始类的方法,method.invoke执行的是子类的方法
Object result = methodProxy.invokeSuper(object, objects);
after();
return result;
}
private void before() {
System.out.println(String.format("log start time [%s] ", new Date()));
}
private void after() {
System.out.println(String.format("log end time [%s] ", new Date()));
}
}
|
需引入 Spring 相关依赖,略。
反射执行
示例
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
| {
public static void main(String[] args) {
testCglibReflect();
}
/**
* log start time [Tue Oct 07 15:58:34 CST 2025]
* UserDao 查询 selectById
* log end time [Tue Oct 07 15:58:34 CST 2025]
* log start time [Tue Oct 07 15:58:34 CST 2025]
* UserDao 更新 update
* log end time [Tue Oct 07 15:58:34 CST 2025]
*/
public static void testCglibReflect() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(UserDao.class);
enhancer.setCallback(new ProxyFactory(new UserDao()));
UserDao userDaoProxy = (UserDao) enhancer.create();
userDaoProxy.select();
userDaoProxy.update();
}
}
class UserDao {
public void select() {
System.out.println("UserDao 查询 selectById");
}
public void update() {
System.out.println("UserDao 更新 update");
}
}
class ProxyFactory implements MethodInterceptor {
private Object origBean;
public ProxyFactory(Object origBean) {
this.origBean = origBean;
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy)
throws Throwable {
before();
Object result = method.invoke(origBean, objects);
after();
return result;
}
private void before() {
System.out.println(String.format("log start time [%s] ", new Date()));
}
private void after() {
System.out.println(String.format("log end time [%s] ", new Date()));
}
}
|
参考文章
Java 动态代理详解
http://juejin.cn/post/6844903744954433544
Java | JDK 动态代理的原理其实很简单
http://juejin.cn/post/6974018412158664734
深入理解 Java 反射和动态代理
https://juejin.cn/post/6844903807755747342
END