1、代理模式简述
代理模式为另一个对象提供一个替身或者占位符以控制对这个对象的访问。在代理模式中,我们创建具有现有对象的对象,以便实现系统控制功能。在外界访问的时候,我们可以添加自己的需求。比如说Spring框架里的AOP、JDK里的Dynamic Proxy、Cglib等。代理模式在各种开发框架和中间件中被广泛使用,比如RPC,数据库访问等。
为什么要用代理模式?
中介隔离作用:在某些情况下,一个客户类不想或者不能直接引用一个委托对象,而代理类对象可以在客户类和委托对象之间起到中介的作用,其特征是代理类和委托类实现相同的接口。
开闭原则,增加功能:代理类除了是客户类和委托类的中介之外,我们还可以通过给代理类增加额外的功能来扩展委托类的功能,这样做我们只需要修改代理类而不需要再修改委托类,符合代码设计的开闭原则。代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后对返回结果的处理等。代理类本身并不真正实现服务,而是同过调用委托类的相关方法,来提供特定的服务。真正的业务功能还是由委托类来实现,但是可以在业务功能执行的前后加入一些公共的服务。例如我们想给项目加入缓存、日志这些功能,我们就可以使用代理类来完成,而没必要打开已经封装好的委托类。
代理模式可分为静态代理和动态代理。
2、静态代理
类图如下:
代码:
/**
* 接口
*/
public interface DataDao {
void insert();
void update();
void delete();
}
/**
* 实现类
*/
public class DataDaoImpl implements DataDao {
@Override
public void insert() {
System.out.println("insert");
}
@Override
public void update() {
System.out.println("update");
}
@Override
public void delete() {
System.out.println("delete");
}
}
/**
* 代理类
*/
public class DataDaoProxy implements DataDao{
private DataDao dataDao;
public DataDaoProxy(DataDao dataDao) {
this.dataDao = dataDao;
}
@Override
public void insert() {
dataDao.insert();
System.out.println("log");
}
@Override
public void update() {
dataDao.update();
System.out.println("log");
}
@Override
public void delete() {
dataDao.delete();
System.out.println("log");
}
}
3、动态代理
动态代理常见的有JDK动态代理和cglib动态代理。
JDK的动态代理是通过反射来实现的。
/**
* JDK代理
*/
public class JDKProxy {
public static void main(String[] args) {
final DataDao dataDao = new DataDaoImpl();
DataDao dataDaoProxy = (DataDao) Proxy.newProxyInstance(dataDao.getClass().getClassLoader(),
dataDao.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before method call ");
Object object = method.invoke(dataDao, args);
System.out.println("after method call ");
return object;
}
});
dataDaoProxy.update();
}
}