java 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
class Car implements Movable {
public void move() {
System.out.println("I'm a car, I'm running...");
}
}
class LogProxy implements Movable {
private Movable movable;
public LogProxy(Movable movable) {
this.movable = movable;
}
public void move() {
// ...logs
this.movable.move();
// ...logs
}
}
// similarity, another proxy just like LogProxy
class AuthProxy implements Movable {
private Movable movable;
public void move() {
//...
}
}
interface Movable {
void move();
}
1
2
3
4
5
6
7
public static void main(String[] args) {
new LogProxy(
new AuthProxy(
new Tank()
)
).move();
}

动态代理

代理不确定类型的对象,生成代理的两种方式:

  • jdk 的动态代理,必须让被代理的类实现某个接口;
  • cglib 生成代理

二者都是使用 ASM 操作二进制文件修改类的属性和方法

jdk 的动态代理的代理类

被代理类一定要实现某个接口,下面先定义接口Actor和被代理类Singer

1
2
3
4
5
6
7
8
9
10
11
12
13
public interface Actor {
void sing();
void dance();
}
public class Singer implements Actor {
public void sing(String song, int volume) {
System.out.println("I'm a singer, I can sing " + song + "at volume " + volume);
}
public void dance() {/*...*/};
}
public class Dancer implements Actor {
//...
}

单例的动态代理类,传入委托类(被代理类),返回动态代理对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class ActorInvocationHandler implements InvocationHandler {
private ActorInvocationHandler() {}
private static ActorInvocationHandler singleton = new ActorInvocationHandler();
private static Class tClass;
public static Object createProxy(Class c) {
tClass = c;
return Proxy.newProxyInstance(tClass.getClassLoader(),
tClass.getInterfaces(), singleton);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("... start singing ...");
Object res = method.invoke(tClass.newInstance(), args);
System.out.println("... end singing ...");
return res;
}
}
1
2
3
4
5
6
public static void main(String[] args) {
Actor actor = (Actor) ActorInvocationHandler.createProxy(Dancer.class);
actor.dance();
Actor singer = (Actor) ActorInvocationHandler.createProxy(Singer.class);
singer.sing("Always with you", 5);
}

cglib实现代理类

对委托类不需要实现接口,但是委托类不能是 final

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class SingerLogInterceptor implements MethodInterceptor {
private SingerLogInterceptor() {}
private static SingerLogInterceptor interceptor = new SingerLogInterceptor();
private static Class targetClass;
private Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("log start...");
Object result = methodProxy.invokeSuper(o, objects);
System.out.println("log end...");
return result;
}
public static Object getInstance(Class c) {
targetClass = c;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(targetClass);
enhancer.setCallback(interceptor);
return enhancer.create();
}
}
1
2
3
4
5
class Singer {
public void sing(String song, int volume) {
System.out.println("I'm a singer, I can sing " + song + "at volume " + volume);
}
}
1
2
3
4
public static void main(String[] args) {
Singer singer = (Singer) SingerLogInterceptor.getInstance(Singer.class);
singer.sing("Always with you", 5);
}
您的支持鼓励我继续创作!