一 概述
通过代理对象访问目标对象,在原有类的行为基础上,加入一些多出的行为,甚至完全替换原有而行为,
静态代理:
代理类必须要有一个被代理对象的引用,静态代理在使用时,需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者是继承相同父类。对于我们不关心的方法,全部委托给被代理的对象的引用,自己处理关心的方法。这种代理是死的,不会在运行时动态创建,而且静态代理的对象很固定。
图形描述和静态代理模式类图如下
/**
* 目标对象实现的接口
* @author jiyukai
*/
public interface BussinessInterface {
void execute();
}
/**
* 目标对象实现类
* @author jiyukai
*/
public class Bussiness implements BussinessInterface{
@Override
public void execute() {
System.out.println("执行业务逻辑...");
}
}
/**
* 代理类,通过实现与目标对象相同的接口
* 并维护一个代理对象,通过构造器传入实际目标对象并赋值
* 执行代理对象实现的接口方法,实现对目标对象实现的干预
* @author jiyukai
*/
public class BussinessProxy implements BussinessInterface{
private BussinessInterface bussinessImpl;
public BussinessProxy(BussinessInterface bussinessImpl) {
this.bussinessImpl = bussinessImpl;
}
@Override
public void execute() {
System.out.println("前拦截...");
bussinessImpl.execute();
System.out.println("后拦截...");
}
}
静态代理的总结
优点:可以做到不对目标对象进行修改的前提下,对目标对象进行功能的扩展和拦截。
缺点:因为代理对象,需要实现与目标对象一样的接口,会导致代理类十分繁多,不易维护,同时一旦接口增加方法,则目标对象和代理类都需要维护。
动态代理:
- 运行期间生成动态代理类
- 代理类需要去实现一个接口:InvocationHandler,实现invoke方法
- 调用Proxy.newProxyInstance(classLoader,interfaces,代理类实例)构造代理对象
- 生成的代理对象调用方法
- 目的:解耦合
一个JDK动态代理的例子
动态代理的类图(只是方便本人理解,与下面的代码不对应)
public interface ISomeService {
String doFirst();
void doSecond();
String doThird();
}
//目标类:代理类要增强的类
public class SomeServiceImpl implements ISomeService {
@Override
public String doFirst() {
return "AAAbbb";
}
@Override
public void doSecond() {
System.out.println("SomeServiceImpl:执行doSecond()");
}
@Override
public String doThird() {
return "aaa";
}
}
public class Mytest {
public static void main(String[] args) {
ISomeService target = new SomeServiceImpl();
ISomeService someService = (ISomeService) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
// proxy:代理对象
// method:目标方法
// args:目标方法的参数列表
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = method.invoke(target, args);
if(result!=null) {
result=((String)result).toUpperCase();
}
return result;
}
});
System.out.println(someService.doFirst());
someService.doSecond();
System.out.println(someService.doThird());
}
}
静态代理和动态代理的区别
- 静态代理在程序运行以前,代理类就应存在了。动态代理类在程序运行时,运行反射机制动态创建而成。
- 静态代理通常只代理一个类,动态代理是代理一个接口下的多个实现类。
- 静态代理事先知道要代理的是什么,动态代理只有在运行时才知道。
使用场景
- 需要修改或者屏蔽一个类或者若干个类的部分方法,复用其他方法,可选择静态代理。
- 若是要拦截一批类中的某些方法,在方法执行前后做一些操作,若这些类有接口,则选择动态代理,否则使用cglib。