动态代理

分类

  • JDK
  • CGLIB
  • Javassist
  • ASM

JDK 动态代理

在 JDK 动态代理中,要实现代理逻辑类必须去实现 java.lang.reflect.InvocationHandler 接口

必须提供接口和实现

接口

1
2
3
public interface Hello {
void say();
}

实现类

1
2
3
4
5
6
7
public class HelloImpl implements Hello{

@Override
public void say() {
System.out.println("hello world!");
}
}

代理对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class HelloProxy implements InvocationHandler {

//真实对象
private Object target = null;

/**
* 建立代理对象和真实对象的代理关系,并返回代理对象
* @param target 真实对象
* @return 代理对象
*/
public Object bind(Object target) {
this.target = target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{
System.out.println("进入代理逻辑方法");
System.out.println("在调度真实对象之前的服务");
Object obj = method.invoke(target, args);//相当于调用say方法
System.out.println("在调度真实对象之后的服务");
return obj;
}
}

Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this)

  • 第一个参数是类加载器
  • 第二个参数是把生成的动态代理对象挂在那些接口下
  • 第三个参数是定义实现方法逻辑的代理类,这里是当前对象,必须实现 InvocationHandler 的 invoke 方法

测试

1
2
3
4
5
6
7
public class Test {
public static void main(String[] args) throws Exception{
HelloProxy helloProxy = new HelloProxy();
Hello proxy = (Hello) helloProxy.bind(new HelloImpl());
proxy.say();
}
}

结果

1
2
3
4
进入代理逻辑方法
在调度真实对象之前的服务
hello world!
在调度真实对象之后的服务

CGLIB动态代理

优势在于不需要提供接口,只要一个非抽象类就能实现动态代理

被代理类

1
2
3
4
5
6
public class HelloImpl2 {

public void say() {
System.out.println("hello world!");
}
}

代理类

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
public class CglibProxy implements MethodInterceptor {

/**
* 生成CGLIB代理对象
* @param clazz Class类
* @return 代理对象
*/
public Object getProxy(Class clazz) {
//CGLIB enhancer 增强类对象
Enhancer enhancer = new Enhancer();
//设置增强类型
enhancer.setSuperclass(clazz);
//定义代理逻辑对象为当前对象,要求当前对象实现MethodInterceptor的intercept方法
enhancer.setCallback(this);
//生成并返回代理对象
return enhancer.create();
}

/**
* 代理逻辑方法
* @param proxy 代理对象
* @param method 方法
* @param args 方法参数
* @param methodProxy 方法代理
* @return 代理逻辑返回
* @throws Throwable
*/
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("调用真实对象前");
Object result = methodProxy.invokeSuper(proxy, args);
System.out.println("调用真实对象后");
return result;
}
}

测试

1
2
3
4
5
6
7
public class Test {
public static void main(String[] args) throws Exception{
CglibProxy proxy = new CglibProxy();
HelloImpl2 obj = (HelloImpl2) proxy.getProxy(HelloImpl2.class);
obj.say();
}
}

结果

1
2
3
调用真实对象前
hello world!
调用真实对象后