代理模式:
代理模式就是需要用一个“代理”身份来间接访问目标类的,实现了在不修改目标类的前提下,对目标方法的增强,扩展功能。
代理模式又分两种:
- 静态代理
- 动态代理
静态代理:
静态代理在编译期间就确定了代理关系,需要手动编写代理类的代理模式。
缺点:
通常一个代理类只为某个限定的类服务,不灵活,应用场景比较少。
构成三要素: 接口类, 目标类, 代理类
实现步骤:
- 创建一个接口和一个实现类
- 创建代理类实现接口
- 将目标对象注入代理类,在代理类中调用对应的目标类中目标方法。
接口:
public interface Meet {
void meet();
}
目标类:
public class President implements Meet {
@Override
public void meet() {
System.out.println("say hello to everyone");
}
}
代理类:
public class PresidentProxy implements Meet {
private President president;
public PresidentProxy(President president) {
this.president = president;
}
@Override
public void meet() {
System.out.println("filter the meeting");
president.meet();
System.out.println("finish the meeting");
}
}
客户端:
public static void main(String[] args) {
President president = new President();
PresidentProxy presidentProxy = new PresidentProxy(president);
presidentProxy.meet();
}
结果:
filter the meeting
say hello to everyone
after the meeting
ER 图

动态代理:
- JDK动态代理
- CGLIB动态代理
JDK动态代理:
构成三要素:接口类,目标实现类,实现InvocationHandler
和静态代理模式一样,也需要一个接口,和一个接口实现的目标类。同时需要一个实现InvocationHandler的代理接口类,注入目标类,通过重写invoke方法实现动态代理。
实现步骤:
- 创建一个接口和一个目标实现类
- 创建代理类实现InvocationHandler接口,通过有参构造方法注入目标实现类,重写invoke增强目标类的方法。
- new 出目标类,通过Proxy.newProxyInstance方式声明出代理类,调用目标方法完成增强扩展。
接口、目标方法都是一样的。
动态代理类public class PresidentJDKProxy implements InvocationHandler {
private President president;
public PresidentJDKProxy(President president) {
this.president = president;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("PresidentJDKProxy filter the meeting");
Object result = method.invoke(president, args);
System.out.println("PresidentJDKProxy finish the meeting");
return result;
}
}
客户端:
public class Main {
public static void main(String[] args) {
President president = new President();
Meet presidentProxy = (Meet) Proxy.newProxyInstance(
President.class.getClassLoader(),
President.class.getInterfaces(),
new PresidentJDKProxy(president));
presidentProxy.meet();
}
}
结果:
PresidentJDKProxy filter the meeting
say hello to everyone
PresidentJDKProxy finish the meeting
CGLIB动态代理:
构成要素:目标类,实现MethodMethodInterceptor的代理实现类
CGLIB动态代理和上述两个代理不太一样,不需要接口,只需要目标类,和实现MethodMethodInterceptor的代理实现类,通过重写intercept方法,增强扩展目标类。大底上和JDK动态代理差不多。
实现步骤:
- 定义目标类
- 自定义MethodMethodInterceptor并重写intercept方法
- 通过Enhancer的create()创建代理类
目标方法不变,可以把接口去掉。
自定义MethodMethodInterceptor类
public class PresidentCGLIBProxy implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("PresidentCGLIBProxy filter the meeting");
Object result = proxy.invokeSuper(obj, args);
System.out.println("PresidentCGLIBProxy finish the meeting");
return result;
}
}
代理工厂类
public class CglibProxyFactory {
public static Object getProxy(Object target) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(new PresidentCGLIBProxy());
return enhancer.create();
}
}
客户端
public class Main {
public static void main(String[] args) {
President president = (President) CglibProxyFactory.getProxy(new President());
president.meet();
}
}
结果
PresidentCGLIBProxy filter the meeting
say hello to everyone
PresidentCGLIBProxy finish the meeting
总结: 如果类存在接口则使用JDK动态代理,如果不存在,则使用CGLIB动态代理。
浙公网安备 33010602011771号