设计模式之代理模式(proxy)
为其他对象提供一种代理以控制对这个对象的访问。代理对象起到中介作用,可去掉功能服务或增加额外的服务。
简单来说,就比如说我们不自己建立服务器,而是购买云服务器,而云服务器需要帮我们安装好系统,调试好网络!
代理方式
- 远程代理:为不同地理的对象,提供局域网代表对象。
- 虚拟代理:根据需要将资源消耗很大的对象进行延迟,真正需要的时候进行创建。
- 保护代理:控制对一个对象访问的权限。
- 智能引用代理:提供对目标对象额外的服务。
代理实现
- 静态代理
- 动态代理
Java 代理模式(proxy)示例
我们以注册用户需要添加日志
静态代理的实现
public interface UserService {
public void add(String name);
}
public class UserServiceImpl implements UserService {
public void add() {
LogHelper.log("注册一个用户 : " + name);
}
}
// 继承方式
public class LogUserServiceImpl extends UserServiceImpl {
@Override
public void add(String name) {
super.add(name);
//写入日志
LogHelper.log("向日志库添加一条插入用户的日志...");
}
}
// 聚合方式
public class LogUserServiceImpl2 implements UserService {
private UserService userService;
public LogUserServiceImpl2(UserService userService)
{
this.userService = userService;
}
@Override
public void add(String name) {
userService.add(name);
//实现开车
LogHelper.log("向日志库添加一条插入用户的日志...");
}
}
public class Test{
public static void main(String[] args) {
//使用继承方式实现
UserService u1 = new LogUserServiceImpl();
u1.add("pangugle");
//使用聚合方式实现
UserService u2 = new UserServiceImpl();
UserService u22 = new LogUserServiceImpl2(u2);
u22.add("baidu");
}
}
但是我们会发现,我们每增加一个逻辑,就要写一个类,每次都要修改,能不能动态来改变了? 答案是可以的;
动态代理实现方式
- JDK动态代理
- CGLIB动态代理
JDK动态代理和CGLIB动态代理的区别
JDK动态代理:
- 只能代理实现了接口的类。
- 没有实现接口的类不能实现JDK的动态代理。
CGLIB动态代理:
- 针对类来实现代理。
- 对指定目标类产生一个子类,通过方法拦截技术拦截所有父类方法的调用。 动态代理的典型应用:spring AOP:同时用到了JDK动态代理和CGLIB动态代理。
JDK动态代理实现日志
public class UserProxy implements InvocationHandler{
private Object target;
public TimeHandler(Object target) {
super();
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
LogHelper.log("添加用户前==========");
method.invoke(target, args);
LogHelper.log("添加用户成功==========");
return null;
}
}
public class Test
{
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
InvocationHandler h = new UserProxy(userService);
Class<?> cls = userService.getClass();
UserService userProxy = (UserService) Proxy.newProxyInstance(cls.getClassLoader(),
cls.getInterfaces(), h);
userProxy.add("pangugle");
}
}
运行结果为
【www.pangugle.com】- 添加用户前==========
【www.pangugle.com】- 注册成功 => pangugle
【www.pangugle.com】- 添加用户成功==========