代理模式
代理模式的作用
我发现学习设计模式遇到的一个最大的困惑就是,自己搞不明白费那么大劲,增加那么多的编码
意义到底时什么。
所以在学习任何一种设计模式的时候,应该最先了解该设计模式到底解决了什么问题。
代理模式的作用是什么呢?
比如说我的同事走了,把手中的代码全部交接给我了,其中有个方法需要进行修改,
然后离开的同事代码写了一大坨没有任何中文注释,嵌套继承用了一大堆,别说改
了就是读明白都感觉困难。这时候怎么办呢?
这时候我们的代理模式就可以华丽登场了。我们可以在不改变源代码的情况下,对原来的
方法进行修改和增强,具体请看如下情况
静态代理
- 接口
public interface ITeacherDao {
void teach();
}
- 被代理类
public class TeacherDao implements ITeacherDao{
@Override
public void teach() {
System.out.println("被代理对象方法执行……");
}
}
- 代理类
public class TeacherDaoProxy implements ITeacherDao{
private ITeacherDao target;
public TeacherDaoProxy(ITeacherDao target) {
this.target = target;
}
@Override
public void teach() {
System.out.println("执行一些方法……");
target.teach();
System.out.println("再执行一些方法……");
}
}
- 调用
public class Client {
public static void main(String[] args) {
TeacherDao teacherDao = new TeacherDao();
TeacherDaoProxy teacherDaoProxy = new TeacherDaoProxy(teacherDao);
teacherDaoProxy.teach();
}
}
- 执行结果
执行一些方法……
被代理对象方法执行……
再执行一些方法……
- 优缺点
优点:在不改变被代理类代码的情况下,对被代理类的方法进行了增强。
缺点:因为代理和被代理类都要实现共同的接口,当接口发生改变时,接口的实现类都要改变。
动态代理
- 接口
public interface ITeacherDao {
void teach();
}
- 被代理类
public class TeacherDao implements ITeacherDao {
@Override
public void teach() {
System.out.println("被代理对象方法执行……");
}
}
- 代理工厂
public class ProxyFactory {
// 维护一个目标对象
private Object target;
// 构造器对target初始化
public ProxyFactory(Object target) {
this.target = target;
}
// 给目标对象生成代理对象
/*
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
ClassLoader:指定当前目标对象使用的加载器,获取加载器的方法固定
Class<?>[]:目标对象实现的接口类型,使用泛型的方式确认类型
InvocationHandler:时间处理,执行目标对象的方法时,会执行处理器方法,会把当前执行的目标对象方法,作为一个参数传入
*/
public Object getProxyInstance(){
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("jdk 代理开始,执行其他方法……");
// 反射机制调用目标对象的方法
Object returnValue = method.invoke(target, args);
System.out.println("jdk 代理结束,执行其他方法……");
return returnValue;
}
});
}
}
- 调用
public class Client {
public static void main(String[] args) {
// 创建目标对象
ITeacherDao target = (ITeacherDao) new TeacherDao();
ITeacherDao proxyInstance = (ITeacherDao)new ProxyFactory(target).getProxyInstance();
// 内存中生成了代理对象
System.out.println(proxyInstance);
System.out.println(proxyInstance.getClass());
proxyInstance.teach();
}
}
- 返回结果
jdk 代理开始,执行其他方法……
被代理对象方法执行……
jdk 代理结束,执行其他方法……
- 优缺点
需要代理什么什么对象,直接在工厂取就可以,但是增强的方法不能随着被代理的对象的改变而改变
Cglib代理
- 没有实现任何接口也可以被代理
- 子类代理,在内存中实现被代理的子类,然后实现动态代理
- 需要下载包,springAop的实现就用到了cglib包
- 如果目标接口需要实现一个接口,就用jdk,如果目标对象不需要实现接口,则用cglib
- 通过字节码生成新的类
出处
https://www.bilibili.com/video/BV1G4411c7N4?p=94