动态代理

举例

1
2
3
4
public interface TestService {
void sayHi();
void sayGood();
}
1
2
3
4
5
6
7
8
9
10
11
12
public class TestServiceImpl implements TestService {

@Override
public void sayHi() {
System.out.println("HI");
}

@Override
public void sayGood() {
System.out.println("GOOD");
}
}

main

1
2
3
4
5
6
7
8
9
10
public class AppTest 
{
@Test
public void test01() {
TestService testService=new TestServiceImpl();
testService.sayHi();
testService.sayGood();
}

}

需求

现在我需要在以上的两个方法之前分别要求输出现在的时间,以及在执行完之后输出“完成”。我们拥有以下几个方法

  1. 直接在sayHi,与saygood方法中添加
  2. 写一个工具类,调用工具类进行添加

以上的两个方法虽然有效,但是如果需要我们更改100个这样的方法,那样岂不是要更改100行

动态代理实现

动态代理可以在程序的执行过程创建代理对象,通过代理对象执行方法,增加额外方法

实现IncocationHandler,功能增加

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.zss.handle;

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

public class MyIncation implements InvocationHandler {
//动态代理的目标对象
private Object object;

public MyIncation(Object object) {
this.object = object;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object res=null;
System.out.println(new Date());
//通过代理对象执行方法shi,会执行这个invoke
res=method.invoke(object,args);
System.out.println("完成");
return res;
}
}

创建代理

1
2
3
4
5
6
7
8
9
10
11
12
13
public class AppTest 
{
@Test
public void test01() {
//创建目标对象
TestService testService=new TestServiceImpl();
InvocationHandler invocationHandler=new MyIncation(testService);
//使用Proxy创建代理
TestService proxy=(TestService) Proxy.newProxyInstance(testService.getClass().getClassLoader(), testService.getClass().getInterfaces(),invocationHandler);
proxy.sayGood();
proxy.sayHi();
}
}

image-20220505154812603

当然如果我们不想要sayhi方法执行一些代码,我们可以在实现IncocationHandler通过判断方法的名称,来选择执行哪一些代码

JDK动态代理是需要声明接口的,创建一个动态代理类必须得给这个”虚拟“的类一个接口。可以看到,这时候经动态代理类创造之后的每个bean已经不是原来那个对象了。

参考:

动态代理实际上是程序在运行中,根据被代理的接口来动态生成代理类的class文件,并加载class文件运行的过程,通过反编译被生成的**$Proxy0.class**文件发现:

class类定义为:为何jdk动态代理必须有接口,不支持仅实现类的代理 - 简书 (jianshu.com)

public final class $Proxy0 extends Proxy implements Interface {

​ *public $Proxy0(InvocationHandler paramInvocationHandler) {*

​ *super(paramInvocationHandler);*

​ ***}***

原理

原理不清楚,插眼!!