静态代理
静态代理也可以看做是代理模式,屏蔽了对真实对象的感知,处理或者调用方法时无需真实对象,只要与代理对象交互即可。主要用于由于安全或者其他原因隐藏真实访问对象,或者是为了提升性能对真实对象进行延迟加载等操作。
代码实例如下:
- 定义一个接口
/**
* 账户接口
*/
public interface Account {
/**
* 查询账户
*/
void query();
/**
* 更新账户
*/
void update();
}
- 实现接口方法
public class AccountImpl implements Account {
static {
System.out.println("初始化操作");
}
@Override
public void query() {
System.out.println("查询账户余额");
}
@Override
public void update() {
System.out.println("更新账户余额");
}
}
- 定义一个代理对象(请注意代码中
getAccount()
方法)
public class AccountProxy implements Account {
private AccountImpl account;
public AccountImpl getAccount() {
if (account == null) {
this.account = new AccountImpl();
}
return account;
}
@Override
public void query() {
System.out.println("查询操作预处理");
// 调用真正的查询账户方法
getAccount().query();
System.out.println("查询操作后回调");
}
@Override
public void update() {
System.out.println("更新操作预处理");
// 调用真正的更新账户方法
getAccount().update();
System.out.println("更新操作后回调");
}
}
- 调用方法
public class Main {
public static void main(String[] args) {
AccountProxy accountProxy = new AccountProxy();
accountProxy.query();
accountProxy.update();
}
}
动态代理
与静态代理不同,动态代理实在运行时动态生成代理类。不需要像静态代理一样为每一个接口写一个代理方法
或者对象,更方便而且利于维护。
动态代理的实现技术有很多,JDK 自带动态处理,CGLIB 和 ASM 库等也都提供了相关的处理方法。
JDK
- 定义一个接口
public interface TaskService {
void complete();
}
- 实现接口方法
public class TaskServiceImpl implements TaskService {
static {
System.out.println("初始化操作");
}
@Override
public void complete() {
System.out.println("完成任务");
}
}
- 代理实现
public class TaskProxy implements InvocationHandler {
private Object target;
public Object bind(Object target) {
this.target = target;
//通过反射机制,创建一个代理类对象实例并返回。用户进行方法调用时使用
//创建代理对象时,需要传递该业务类的类加载器(用来获取业务实现类的元数据,在包装方法是调用真正的业务方法)、接口、handler实现类
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result;
System.out.println("预处理操作");
result = method.invoke(target, args);
System.out.println("回调操作");
return result;
}
}
- 运行
public class Main {
public static void main(String[] args) {
TaskServiceImpl taskServiceImpl = new TaskServiceImpl();
TaskProxy proxy = new TaskProxy();
TaskService taskService = (TaskService) proxy.bind(taskServiceImpl);
taskService.complete();
}
}
CGLIB
由于该种实现是基于 extend 的方式,所以对于 final 类型的方法无法进行代理执行
- 方法定义
public class ProcessService {
public void start() {
System.out.println("流程启动处理");
}
}
- 代理
public class ProcessServiceAgent implements MethodInterceptor {
private Object target;
public Object getInstance(Object object) {
this.target = object;
Enhancer enhancer = new Enhancer();
//为加强器指定要代理的业务类(即:为下面生成的代理类指定父类)
enhancer.setSuperclass(this.target.getClass());
//设置回调:对于代理类上所有方法的调用,都会调用CallBack,而Callback则需要实现intercept()方法进行拦
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("预处理操作");
methodProxy.invokeSuper(o, objects);
System.out.println("回调操作");
return null;
}
}
- 运行
public class Main {
public static void main(String[] args) {
ProcessService processService = new ProcessService();
ProcessServiceAgent processServiceAgent = new ProcessServiceAgent();
ProcessService instance = (ProcessService) processServiceAgent.getInstance(processService);
instance.start();
}
}
其他
常用的应用场景
- 远程代理
- 虚拟代理
- 安全代理
- 指针引用
- 延迟加载
文档参考
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于