代理模式是对象的结构模式。代理模式给某一个对象提供一个代理对象,并由代理对象控制原对象的引用。
代理模式的示意性实现类图如下
- 抽象主题角色:声明了真实主题与代理主题的共同接口,这样在可以使用真实主题的地方都可以使用代理主题。
- 代理主题角色:包含了一个对真实主题角色的引用,从而可以在任何时候操作真实主题角色。
代理模式的时序图如下
代理模式是怎样工作的:
- 代理主题并不改变主题的接口,因为模式的用意是不让客户端感觉到代理的存在。
- 代理使用委派将客户端的调用传递给真实主题对象,代理起的到是一个传递请求的作用。
- 代理主题在传递调用之前和之后都可以执行特定的操作,而不是单纯的传递请求。
JDK动态代理
jdk的动态代理是基于接口的,必须实现了某一个或多个任意接口才可以被代理,并且只有这些接口中的方法会被代理。
在Dao类的方法调用前输出xxx方法 start
public interface UserDao {
public void save();
public void delete();
}
public class UserDaoImpl implements UserDao {
@Override
public void delete() {
// TODO Auto-generated method stub
System.out.println("deleted");
}
@Override
public void save() {
// TODO Auto-generated method stub
System.out.println("save");
}
}
public class DaoProxy implements InvocationHandler {
private Object target;
public Object getTarget() {
return target;
}
public void setTarget(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println(method.getName()+" start!");
method.invoke(target,args);
return null;
}
}
public static void main(String[] args) {
UserDao uDao = new UserDaoImpl();
DaoProxy log = new DaoProxy();
log.setTarget(uDao);
UserDao uDaoProxy = (UserDao)Proxy.newProxyInstance(uDao.getClass().getClassLoader(),
uDao.getClass().getInterfaces(), log);
uDaoProxy.delete();
uDaoProxy.save();
}
运行结果
delete start!
deleted
save start!
save
deleted
save start!
save
CGlib
- cglib(Code Generation Library)是一个强大的,高性能,高质量的Code生成类库。它可以在运行期扩展Java类与实现Java接口。
- cglib封装了asm,可以在运行期动态生成新的class。
- cglib用于AOP,jdk中的proxy必须基于接口,cglib却没有这个限制。
Spring中AOP是基于代理的思想来实现,其代理就是基于CGlib来实现的。
参考:《Java与模式》