Java 设计模式之代理模式 -- 复习
静态代理和动态代理的 Java 实现方式
关于代理模式的基本概念就不在此处描述了,本文主要是根据简单的代码实现静态和动态代理
静态代理主要通过代理类注入被代理对象,然后调用代理对象方法前后实现增强
动态代理则是有两种方式:JDK API 和 CGLIB
前者被代理类必须实现接口,后者不用但是被代理类不可被final修饰,被代理方法不可被final修饰
静态代理:
静态代理的实现方式比较简单,代理类注入被代理对象,然后在执行被代理对象方法前后设置需要增强的内容
// 静态代理
// 接口
interface SmsService {
void sendMsg(String msg);
}
// 实现类
class SmsServiceImpl implements SmsService {
@Override
public void sendMsg(String msg) {
System.out.println("发送邮件: " + msg);
}
}
// 静态代理类, 注意此处使用了lombok插件生成构造函数
@AllArgsConstructor
@NoArgsConstructor
class SmsProxy implements SmsService {
private SmsService smsService;
// 注入被代理对象,然后静态实现增强
@Override
public void sendMsg(String msg) {
System.out.println("发送邮件前...");
smsService.sendMsg(msg);
System.out.println("发送邮件后...");
}
// 测试方法
public static void main(String[] args) {
SmsProxy proxy = new SmsProxy(new SmsServiceImpl());
proxy.sendMsg("早上好!");
}
}
// 输出结果
发送邮件前...
发送邮件: 早上好!
发送邮件后...
动态代理: JDK API 方式
// 动态代理 JDK API 方式
// 被代理接口
interface SmsService {
void sendMsg(String msg);
}
// 被代理实现类
class SmsServiceImpl implements SmsService {
@Override
public void sendMsg(String msg) {
System.out.println("发送每日邮件: " + msg);
}
}
// 代理handler,此处完成代理, 注意此处使用了lombok插件和注解生成构造函数
@NoArgsConstructor
@AllArgsConstructor
class JDKProxyHandler implements InvocationHandler {
// 注入被代理对象
private SmsService smsService;
// 代理
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("发送邮件前...");
// 第一个参数是被代理对象
// 第二个参数是执行方法的参数
Object result = method.invoke(smsService, args);
System.out.println("发送邮件后...");
return result;
}
}
// 生成代理对象的工厂
class JDKProxyFactory {
public static SmsService getInstance(SmsService smsService) {
return (SmsService)
// 该方法三个参数分别为:
// 1.被代理类的接口类对象的类加载器
// 2.被代理类的接口类对象的字节码
// 3.实现了InvocationHandler接口的子类
Proxy.newProxyInstance(smsService.getClass().getClassLoader(),
smsService.getClass().getInterfaces(),
new JDKProxyHandler(smsService));
}
}
class Main {
// 测试
public static void main(String[] args) {
SmsService instance = JDKProxyFactory.getInstance(new SmsServiceImpl());
instance.sendMsg("早安!");
}
}
动态代理: cglib 方式
// 动态代理 CGLIB 方式
// 被代理类,可不实现接口
class SmsServiceImpl {
public void sendMsg(String msg) {
System.out.println("发送每日邮件:" + msg);
}
}
// 代理处理handler
class CglibProxyHandler implements MethodInterceptor {
// 此处实现代理
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("cglib代理之前...");
// 注意此处和JDK代理的不同,方法是使用MethodProxy执行
// 且调用的方法为invokeSuper而不是invoke
// 并且代理对象直接是方法参数o,不需要手动注入了
Object result = methodProxy.invokeSuper(o, objects);
System.out.println("cglib代理之后...");
return result;
}
}
// 工厂
class CglibProxyFactory {
public static SmsServiceImpl getInstance(SmsServiceImpl smsService) {
// 通过Enhancer对象实现代理
Enhancer enhancer = new Enhancer();
// 设置类加载器
enhancer.setClassLoader(smsService.getClass().getClassLoader());
// 设置字节码
enhancer.setSuperclass(smsService.getClass());
// 设置回调方法(代理类)
enhancer.setCallback(new CglibProxyHandler());
// 生成代理对象并返回
return (SmsServiceImpl) enhancer.create();
}
}
// 测试类
class Main {
public static void main(String[] args) {
SmsServiceImpl instance = CglibProxyFactory.getInstance(new SmsServiceImpl());
instance.sendMsg("good morning!");
}
}