动态代理(个人理解)
前言
其实之前对代理模式就是一个模糊的概念,大概知道是什么,什么作用,大概能看懂,都是个大概,通病啊,所以借此自己好好的看一下,这也是写博客的好处之一,因为自己需要完整的记录下来,所以自己的思维就需要先明确好
AOP作为spring几大核心之一,其实现原理就是动态代理+反射,所以说,作为核心功能的它,怎能不去好好熟悉下呢
推荐先看开头的参考文章,大佬们写的很不错,了解后发现也不难理解.动态代理就是在不动原代码(目标)的情况下,对其进行功能扩展. 原目标正常执行自己的功能即可,增强只需要在代理类上增加就可以了
静态代理
有动态代理,肯定就有静态代理,就像学习前端一样,开始先从静态页面学习,慢慢的在深入到动态的演变,引用文章的结论:
代理实现类持有真实对象的引用,客户端不直接与真实对象交互,而是调用代理类,这样使得代理类可以在真实行为前后做一些扩展操作
这里就不示范了,参考如下
JDK动态代理
jdk和cglib最大的区别就是: jdk代理必须且只能由接口对象接收
定义接口对象:
public interface ActionInfo {
void action();
}
实现类(目标对象)
public class Ikun implements ActionInfo {
@Override
public void action() {
System.err.println("Ikun 唱,跳,rap");
}
}
代理类
public class JdkProxy implements InvocationHandler {
//被代理的主体事件(ikun)
private Object bean;
public JdkProxy(Object bean) {
this.bean = bean;
}
/**
* 代理方法
* @param proxy 被代理的主体事件
* @param method 被代理的方法
* @param args 方法的参数
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//根据调用的方法名判断可以自定义后面的操作
String methdName=method.getName();
if (methdName.equals("action")){
//你使用代理需要干嘛?总得是或前或后的要做些其他事情吧
//开始代理操作
System.err.println("我是ikun代理人,架起了相机");
}else if (methdName.equals("action2")){
System.err.println("自定义2");
}
//被代理对象(Ikun)开始自己的表演,注意代理只做代理的事情,源目标该干嘛还是干嘛,不会影响
method.invoke(bean,args);
//代理结束
System.err.println("我是ikun代理人,录制结束");
return null;
}
}
测试:
public static void main(String[] args) {
//原对象 ikun={Ikun@560}
Ikun ikun = new Ikun();
//谁被代理,是Ikun,唱跳rap最终只能Ikun去完成
JdkProxy jdkProxy = new JdkProxy(ikun);
//这里是能是接口对象接收,ActionInfo这里已经变成了代理对象,看图片可知 actioninfo={$Proxy0@591}
ActionInfo actionInfo=(ActionInfo) Proxy.newProxyInstance(jdkProxy.getClass().getClassLoader(),
ikun.getClass().getInterfaces(),
jdkProxy);
//调用事件,开始代理操作,进入JdkProxy
actionInfo.action();
}
//ikun的工作是唱跳rap(将要被代理的对象,就是原本一段要被执行的代码),
// 但现在想要录视频直播(使用代理模式需要干什么,达成什么效果),
// 所以就需要准备些东西,代理人开始干自己想要干的事,准备相机,直播房间(代理过程中,执行的功能增强,达到自己想要的效果)
// 任然不会影响到ikun唱ji你太美,他原本该干嘛,就还是干嘛(不会影响到原本的代码,只是在它发生前后执行些其他代码)
Cglib代理
cglib区别就是不用在局限于接口,Cglib是通过生成子类来实现的,代理对象既可以赋值给实现类,也可以赋值给接口
public class CglibProxy implements MethodInterceptor {
//谁被代理,也就是ikun
private Object bean;
public CglibProxy(Object bean) {
this.bean = bean;
}
//封装一下代理对象的创建,这里只是方便后面调用
private Enhancer enhancer=new Enhancer();
public Object gePryxy(){
//重点:设置需要创建子类的类,准备创建子类实例,这里会生成一个被代理对象(ikun)的子类,看下图
enhancer.setSuperclass(bean.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
//这里和jdk的方式差不多的
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
//根据调用的方法名判断可以自定义后面的操作
String methdName=method.getName();
if (methdName.equals("action")){
//你使用代理需要干嘛?总得是或前或后的要做些其他事情吧
//开始代理操作
System.err.println("我是ikun代理人,架起了相机");
}else if (methdName.equals("action2")){
System.err.println("自定义2");
}
// methodProxy.invokeSuper(o,objects);//和下面效果一样
method.invoke(bean,objects);
System.err.println("我是ikun代理人,录制结束-");
return null;
}
}
测试
public static void main(String[] args) {
Ikun ikun1 = new Ikun();
CglibProxy cglibProxy=new CglibProxy(ikun1);
//这里可以是接口,也可以是对象接收
Ikun ikun=(Ikun)cglibProxy.gePryxy();
ikun.action();
}
//光从代码可以看出,cglib要比jdk简洁一下,最主要是会自己生成原有bean对象子类,不需要像jdk只能用接口.
//并且速度和性能会更优
总结:这也只是清楚了它的步骤流程,大概的一个思想,底层的东西暂时还没去了解.到这里不难发现,这些东西真的挺深挺厉害的,而我只是活在了一个皮毛世界