关于Java代理那些事儿

代理是啥?就是代替你执行你持有的主要功能,并且能在你的基础之上完成一些其他的功能。代理的目的就是生成一个和原对象具有同样功能的对象。在Java中,代理是一种设计模式。在Spring的面向切面编程(AOP)中,主要就是利用动态代理来实现代码的织入。

代理分为动态代理和静态代理。顾名思义,动态代理比静态代理扩展性更高,动态代理不用为每一个实现类维护一个代理类。

静态代理

为不同的被代理类都维护一个代理类,维护工作量大,不利于扩展。

建立接口类,即被代理类。

Worker.java 工人接口类

1
2
3
4
5
6
public interface Worker {

public void working();

public void resting();
}

SimpleWorker.java 工人实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
public class SimpleWorker implements Worker {

@Override
public void working() {
System.out.println("I'm working!");
}

@Override
public void resting() {
System.out.println("I'm resting!");
}

}

需求,通过代理调用SimpleWorker的具体的方法,且处理其他逻辑(输出一句话):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class WorkerProxy {

private Worker worker;

// 构造函数传入需要执行的类
public WorkerProxy(Worker worker) {
this.worker = worker;
}

// 代理方法,调用具体实现方法
public void working() {
System.out.println("excute static proxy.");
worker.working();
}
}

运行结果:

1
2
excute static proxy.
I'm working!

动态代理

动态代理分为JDK动态代理与CGLIB动态代理。

JDK动态代理

JDK动态代理是jre库提供的一种方法,无需额外引入。它是通过类的接口生成代理类。

生成一个jdk代理,需要实现InvocationHandler接口,重写invoke方法。再用Proxy.newProxyInstance去生成代理类。

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
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
* jdk 动态代理
* @author guilin
*
*/
public class JdkProxy implements InvocationHandler{

private Object target;

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

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

public Object getInstance() {
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
}

测试类:

1
2
3
4
5
6
7
8
9
10
public class Test {
public static void main(String[] args) {
// JDK 动态代理
SimpleWorker simpleWorker = new SimpleWorker();
JdkProxy dynamicProxy = new JdkProxy(simpleWorker);
Object proxyObj = dynamicProxy.getInstance();
Worker obj = (Worker) proxyObj;
obj.working();
}
}

运行结果:

1
2
excute jdk proxy.
I'm working!

CGLIB动态代理

CGLIB是通过继承父类的公有方法,然后进行重写来实现的。在代码中代理类需要实现MethodInterceptor接口,重写intercept方法。配合Enhancer生成动态代理类。

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
import java.lang.reflect.Method;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

public class CglibProxy implements MethodInterceptor{

@Override
public Object intercept(Object obj, Method method, Object[] aobj, MethodProxy methodproxy) throws Throwable {
System.out.println("excute cglib proxy.");
// 执行父类方法
Object result = methodproxy.invokeSuper(obj, aobj);
return result;
}

public Object getInstance(Class<?> superClass) {
// 获取代理实例
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(superClass);
enhancer.setCallback(this);
return enhancer.create();
}

}

测试类:

1
2
3
4
5
6
7
8
9
public class Test {
public static void main(String[] args) {
// CGLIB 动态代理
CglibProxy cglibProxy = new CglibProxy();
Object instance = cglibProxy.getInstance(SimpleWorker.class);
Worker obj2 = (Worker) instance;
obj2.working();
}
}

运行结果:

1
2
excute cglib proxy.
I'm working!

Spring 默认使用jdk动态代理,而当类没有接口类时,使用CGLIB进行代理。

查看评论