设计模式-代理模式
一、什么是代理模式
代理模式是为其他对象提供一种代理以控制对这个对象的访问。这种功能只有在编译无法确定要实现哪个接口时才有必要使用。利用代理可以创建一个实现了一组接口的新类。代理类与被代理类必须实现同一个接口,代理对象是在运行时由调用处理器定义的新类,它有一个名字,如$Proxy0。代理对象一旦被创建,与虚拟机上的任何其他类没有什么区别。
代理模式本质上是不改变原有功能的基础上,增加新的功能,如日志、权限等,Spring AOP的实现原理就是基于代理模式
二、为什么要用代理模式
-
中介隔离作用:在某些情况下,一个客户类不想或者不能直接引用一个委托对象,而代理类对象可以在客户类和委托对象之间起到中介的作用,其特征是代理类和委托类实现相同的接口。
-
开闭原则:增加功能:代理类除了是客户类和委托类的中介之外,我们还可以通过给代理类增加额外的功能来扩展委托类的功能,这样做我们只需要修改代理类而不需要再修改委托类,符合代码设计的开闭原则。代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后对返回结果的处理等。代理类本身并不真正实现服务,而是同过调用委托类的相关方法,来提供特定的服务。真正的业务功能还是由委托类来实现,但是可以在业务功能执行的前后加入一些公共的服务。例如我们想给项目加入缓存、日志这些功能,我们就可以使用代理类来完成,而没必要打开已经封装好的委托类。
三、三种代理模式
- 静态代理
- jdk动态代理
1.首先创建服务接口
public class SmsServiceImpl implements SmsService{
@Override
public interface SmsService {
String sendMsg(String msg);
}
}
2.实现服务接口
public class SmsServiceImpl implements SmsService{
@Override
public String sendMsg(String msg) {
System.out.println("send msg:"+msg);
return msg;
}
}
3.创建代理类
public class JdkProxyFactory {
/**
* 获取某个类的代理对象
* @param target
* @return
*/
public static Object getProxy(Object target){
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),//目标类加载
target.getClass().getInterfaces(),//代理需要实现的接口,可指定多个
// 使用lambda表达式实现,相当于
/*new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return null;
}
}*/
(Object proxy, Method method, Object[] args)->{
// before do something...
Object result = method.invoke(target, args);
// after do something...
return result;
}
);
}
}
4.调用代理
public static void main(String[] args) {
SmsService smsService = (SmsService) JdkProxyFactory.getProxy(new SmsServiceImpl());
smsService.sendMsg("hello john");
}
- Cglib代理
上述例子,我们发现要实现jdk动态代理,必须定义服务接口,在我们实际开发中如果出现被代理类未实现接口,此时我们可以使用cblib动态代理
创建cglib代理类
public class CglibProxyFactory {
public static Object getProxy(Class<?> classz){
//创建动态代理增强类
Enhancer enhancer =new Enhancer();
//设置类加载器
enhancer.setClassLoader(classz.getClassLoader());
//设置被代理类
enhancer.setSuperclass(classz);
//设置方法拦截器
enhancer.setCallback(
(MethodInterceptor) (o, method, objects, methodProxy) -> {
// do something
Object object = methodProxy.invokeSuper(o,objects);
// do something
return object; });
//创建代理类
return enhancer.create();
}}
调用代理
SmsServiceImpl smsService = (SmsServiceImpl)CglibProxyFactory.getProxy(SmsServiceImpl.class);
smsService.sendMsg("hello");