代理模式
代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。
按照代理的创建时期,代理类可以分为两种。
静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。
动态代理:在程序运行时,运用反射机制动态创建而成。
先来个接口(JDK动态代理是基于接口的)
package proxyTest;
public interface Count {
void queryCount();
void updateCount();
}
实现类
package proxyTest;
public class CountImpl implements Count{
@Override
public void queryCount() {
System.out.println("query count....");
}
@Override
public void updateCount() {
System.out.println("update count....");
}
}
问题 要在查询之前之后做一些操作 比如记录日志 校验权限之类的
静态代理开始
package proxyTest;
public class CountProxy implements Count {
Count count;
public CountProxy(Count count ) {
this.count = count;
}
@Override
public void queryCount() {
System.out.println("query start....");
count.queryCount();
System.out.println("query end....");
}
@Override
public void updateCount() {
System.out.println("update start....");
count.updateCount();
System.out.println("update end....");
}
}
测试
Count count = new CountProxy(new CountImpl());
count.queryCount();
count.updateCount();
以上静态代理,可以简单粗暴的实现我们的要求,但是不好扩展,不方便。
下面介绍动态代理,其实原理是一样的
/**
* JDK动态代理类
* @author zhoushiwen
*
*/
public class CountJDKProxy implements java.lang.reflect.InvocationHandler {
private Object target;
/**
* 绑定委托对象并返回一个代理类
* @param target
* @return
*/
public Object bind(Object target) {
this.target = target;
//取得代理对象
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object o = null;
System.out.println("开始。。。。");
o = method.invoke(target, args);
System.out.println("结束。。。。");
return o;
}
}
注意:JDK的代理对象必须实现接口,有一定的局限性。
cglib弥补了这一缺陷
测试
CountJDKProxy cjp = new CountJDKProxy();
Count count = (Count) cjp.bind(new CountImpl());
count.queryCount();
count.updateCount();
spring的AOP也是利用动态代理实现的