一. 概述
1. 什么是代理模式?
代理模式:提供一个代理对象来控制被代理对象的访问,在客户端和原对象之前起到中介的作用
2.为什么用代理模式?
当一个对象不适合或不能直接引用另一对象时,使用代理模式可以起到隔离作用,代理类和被代理类实现相同的接口,还可以通过代理类增加额外功能来扩展被代理类,符合代码设计的开闭原则
3.代理模式的角色?
- 抽象主题(Subject):代理类和被代理类的共同接口
- 具体主题(RealSubject):被代理类
- 代理主题(Proxy):代理类
二. 代理模式
1. 静态代理
抽象主题:创建一个接口
public interface IUserDao {
void save();
}
具体主题:创建被代理类
public class UserDao implements IUserDao {
public void save(){
System.out.println("保存了用户");
}
}
代理主题:创建代理类
public class ProxyUserDao implements IUserDao {
private IuserDao iUserDao;
//创建构造器,初始化时传入被代理对象
//用接口类作为构造器参数,可以传入实现此接口的任何被代理类
public ProxyUserDao(IuserDao iUserDao){
this.iUserDao = iUserDao;
}
public void save(){
System.out.println("代理方法进行一些准备工作");
iUserDao.save();//执行被代理类中的方法
Sytem.out.println("代理方法进行一些后续工作")
}
}
测试
public class ProxyTest {
public static void main(String[] args) {
//1.创建被代理对象
UserDao userDao = new UserDao();
//2.创建代理对象,用被代理对象初始化
ProxyUserDao proxy = new ProxyUserDao(userDao);
proxy.save();
}
}
执行结果
代理方法进行一些准备工作
保存了用户
代理方法进行一些后续工作
- 优点:在不改变原类代码的前提下,对其进行功能扩展
- 缺点:越多的扩展,导致实现相同接口的代理类增多,难以维护
2. JDK 动态代理
核心代码:Proxy.newProxyInstance(类加载器,接口,InvocationHandler)
public class ProxyFactory{
//返回一个代理类的对象
public static Object getProxyInstance(Object obj){
MyInvocationHandler handler = new MyInvocationHandler(obj);
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),//参数1:与被代理类相同的类加载器
obj.getClass().getInterfaces(),//参数2:与被代理类需要实现的相同接口
handler);//参数3:InvocationHandler,可以直接用匿名内部类
}
}
class MyInvocationHandler implements InvocationHandler{
private Object obj;
public MyInvocationHandler(Object obj){
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//(插入自定义增强代码)
return method.invoke(obj,args); //被代理对象中的方法
}
}
测试
public class ProxyTest {
public static void main(String[] args) {
//1.创建被代理对象
UserDao userDao = new UserDao();
//2.创建代理对象
IUserDao proxy = (IUserDao) ProxyFactory.getProxyInstance(userDao);
proxy.save();
}
}
3. CGLIB 动态代理
对于没有接口的类,使用 CGLIB 实现动态代理
核心代码:Enhancer.create(反射类型,MethodInterceptor)
//创建拦截器
public class MyMethodInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("准备工作");
Object object = methodProxy.invokeSuper(o, args);
System.out.println("后续工作");
return object;
}
}
public class ProxyTest {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(UseDao.class);
enhancer.setCallback(new MyMethodInterceptor());
UserDao proxy = (UserDao) enhancer.create();
proxy.save();
}
}