代理设计模式
特征:代理类与委托类(被代理类)有同样的接口,代理类负责消息预处理、把消息转发给委托类,以及事后处理消息等。代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。
代理类可以分为两种:静态代理和动态代理
静态代理例子:
接口
public interface Count {
void queryCount();
void updateCount();
}
委托类
public class CountImpl implements Count {
@Override
public void queryCount() {
System.out.println("查看账户方法...");
}
@Override
public void updateCount() {
System.out.println("修改账户方法...");
}
}
代理类
public class CountProxy implements Count {
private CountImpl countImpl;
public CountProxy(CountImpl countImpl) {
this.countImpl = countImpl;
}
@Override
public void queryCount() {
System.out.println("事务处理之前");
// 调用委托类的方法;
countImpl.queryCount();
System.out.println("事务处理之后");
}
@Override
public void updateCount() {
System.out.println("事务处理之前");
// 调用委托类的方法;
countImpl.updateCount();
System.out.println("事务处理之后");
}
}
测试类
public class TestCount {
public static void main(String[] args) {
CountImpl countImpl = new CountImpl();
CountProxy countProxy = new CountProxy(countImpl);
countProxy.updateCount();
countProxy.queryCount();
}
}
静态代理的特点:
每一个代理类只能为一个接口服务,这样一来程序开发中必然会产生过多的代理,而且,所有的代理操作除了调用的方法不一样之外,其他的操作都一样,则此时肯定是重复代码,解决方法是用动态代理实现。
动态代理的例子:
接口
public interface Shape {
void huat();
}
委托类
public class Circle implements Shape {
@Override
public void huat() {
System.out.println("implement Circle");
}
}
动态代理类
public class InvocationHandlerImpl implements InvocationHandler {
private Object target;
//构造改对象时,要传入相应的委托类对象
public BookFacadeProxy(Object target){
this.target=target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result = null;
System.out.println("事物开始");
// method是传入的方法名称,target表示在此对象上调用该方法,args传入该方法的参数
result = method.invoke(target, args);
System.out.println("事物结束");
return result;
}
}
测试类
public class TestProxy {
public static void main(String[] args) {
Circle c=new Circle();
InvocationHandlerImpl invokeImpl=new InvocationHandlerImpl (c);
//用Proxy类的静态方法,动态地创建代理对象
//第1个参数表示加载委托类的类加载器,第2个表示委托类实现的接口
//第3个表示InvocationHandler类型的对象,是实际代理逻辑实现的地方
Shape s=(Shape)Proxy.newProxyInstance(c.getClass().getClassLoader(), c.getClass().getInterfaces(), invokeImpl);
//在代理对象上调用方法
s.xi();
}
}
可以看到,采用动态代理,不需要为每个接口编写代理类,代理类对象的生成对所有的接口都是通用的,可以传入不同委托类实例,来生成相应的代理对象。但是,它也有缺点,该方法只能代理实现了接口的类。对没有实现接口的类没法代理。
对没有实现接口的类进行代理,我们可以采用cglib开源框架来实现
例子:
委托类
public class BookFacadeImpl1 {
public void addBook() {
System.out.println("增加图书的普通方法...");
}
}
代理类
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class BookFacadeCglib implements MethodInterceptor {
private Object target;
/**
* 创建代理对象
*
* @param target
* @return
*/
public Object getInstance(Object target) {
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
// 回调方法
enhancer.setCallback(this);
// 创建代理对象
return enhancer.create();
}
@Override
// 回调方法
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
System.out.println("事物开始");
proxy.invokeSuper(obj, args);
System.out.println("事物结束");
return null;
}
}
测试类
public class TestCglib {
public static void main(String[] args) {
BookFacadeCglib cglib = new BookFacadeCglib();
BookFacadeImpl1 bookCglib = (BookFacadeImpl1) cglib
.getInstance(new BookFacadeImpl1());
bookCglib.addBook();
}
}