静态代理和动态代理
本篇文章是通过看视频学习总结的内容, 如有错误的地方请谅解,并联系博主及时修改,谢谢您的阅读.
什么是代理?
在生活中,其实也出现很多代理,比如卖/租房子的中介,送快递的小哥都属于一种代理,代理的本身其实就是代替某人去完成某件事情,被完成的事情实际上自己也能办到,只是没必要自己亲自去做,好比租房子的时候,可以直接去找房东租房,也可以去找房屋中介所,其实最终完成的事情就是租房这件事情。
什么是静态代理?
静态代理,举个例子。老王的儿子年纪大了,该成家了,但是儿子却没有对象,不着急,new
一个就可以了!于是老王就征求到儿子的要求,开始为儿子寻找匹配儿子需求的对象。天下那么多单身汉,不可能老王一个人都能完成所有单身汉对象的代理,所以这里就被称为了静态代理。
什么是动态代理?
根据老王为儿子寻找对象的案例中延申出了一种职业婚介所
,婚介所就能够同时代理很多人寻找对象的功能,不像老王一样只针对自己的儿子寻找对象,而是面向了整个社会,所以像这种可以灵活的代理,被称为动态代理。
以上全是自己个人的理解,如有错误的地方,看官请指正,谢谢啦。
一、 使用静态代理,该案例用找对象的方式来列举。
- 先分析一波,既然是找工作,那么
BOOS直聘
和前程无忧
这些平台共同的特点都是为客户提供一份工作,那么可以新建一个接口IPerson
,新增抽象方法void mating();
public interface IPerson {
/** 找对象行为 **/void mating();
}
- 接口设计好后,
Jack
开始为自己的儿子Tom
寻找对象
public class Tom implements IPerson{
@Overriedpublic void mating(){
System.out.println("是个女的就行!");}
}
- 使用静态代理,
Jack
为tom
寻找对象
public class Jack implements IPerson{
private Tom tom;public Jack(Tom tom){
this.tom = tom;}@Overriedpublic void mating(){
System.out.println("jack..开始给tom寻找对象");System.out.println("jack..发现了不错的对象");this.tom.mating();System.out.println("tom和他的对象开始交往。。。");}
}
- 测试
// 测试客户端
public class ClientStaticProxy {
public static void main(String[] args) {
OldTom oldTom = new OldTom(new Tom());oldTom.mating();}
}// 输出结果
// jack..开始给tom寻找对象
// jack..发现了不错的对象
// 是个女的就行!
// tom和他的对象开始交往。。。
二、 使用JDK
动态代理
- 使用
Jdk
动态代理就好比婚介所,婚介所可以代理更多的人找对象,无论男女老,没有少,就比Jack
给儿子找对象灵活 - 在原有的
Tom
找对象的基础上增加一个mark
也找对象
// 新增mark也开始找对象
public class Mark implements IPerson{
@Overriedpublic void mating(){
System.out.println("Mark: 年薪百万~");}
}
- 使用
JDK
动态代理来对tom
和mark
两个人进行代理
// 使用jdk动态代理,需要实现InvocationHanlder中invoke方法
public class JdkProxy implements InvocationHanlder{
private IPerson target;// 调用instance方法启动jdk动态代理public IPerson getInstance(IPerson person){
this.target = person;Class<? extends IPerson> clazz = this.target.getClass();return (IPerson)Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);}@Overriedpublic Object invoke(Object obj, Method method, Object[] objects){
System.out.println("开始为 '" + this.target.getClass().getSimpleName() + "'寻找对象..");// this.target 是被代理的对象, objects是反射调用方法的形参Object result = method.invoke(this.target, objects);System.out.println("通过代理的方式成功寻找到了对象,开始交往...");return result;}
}
- 客户端
public class JdkProxyClient{
public static void main(String[] args){
// IPerson target = new Mark();IPerson target = new Tom();Tom tom = (Tom)new JdkProxy(target);tom.mating();}
}
// 输出结果,
// 开始为 'Tom' 寻找对象..
// Mark: 年薪百万~
// 通过代理的方式成功寻找到了对象,开始交往...
三、 使用CGLIB
动态代理
- 使用
CGLIB
实现动态代理只需要修改Proxy
类,原有的IPerson
和Tom
,Mark
不做修改
public class CglibProxy implements MethodInterceptor{
public Object instance(Class<?> clazz){
Enhancer enhancer = new Enhancer();// 获取继承该类的所有类enhancer.setSuperclass(clazz);enhancer.setCallback(this);return enhancer.create();}@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("开始为 '" + method.getDeclaringClass().getSimpleName() + "'寻找对象..");Object result = methodProxy.invokeSuper(o, objects);System.out.println("通过代理的方式成功寻找到了对象,开始交往...");return result;}
}
- 客户端
public class CglibProxyClient{
public static void main(String[] args){
// IPerson target = new Mark();IPerson target = new Tom();Tom tom = (Tom)new JdkProxy(target);tom.mating();}
}
// 输出结果,
// 开始为 'Tom' 寻找对象..
// Mark: 年薪百万~
// 通过代理的方式成功寻找到了对象,开始交往...
四、 总结
- 虽然在日常开发中很少会使用到动态代理到业务逻辑中, 但是并不影响对动态代理的学习.
- 动态代理和静态代理的区别在于动态代理使用了反射加载字节码的方式重新代理的新的对象, 而静态代理则是非读取字节码的方式来代理.
- 动态代理在很多框架中都被使用到, 目前
Cglib
和Jdk
动态代理,Cglib
在Spring
框架中使用的是最多的, 有兴趣可以看看源码. - 总而言之, 静态代理的局限被动态代理打破了,不再局限代理某一个类.