面试官问你设计模式 你还在答复单例 和 工厂 ? 代理模式理解一下

走过路过不要错过,上一篇讲了反射,能够看我上一篇文章或微信上搜寻:木子的昼夜编程 。

这一篇筹备写一下动静代理模式。

1. 理由

先给你一个理由,为什么学动静代理

第一他是一种设计模式,在你工作中如果能够联合它的应用,那代码相对丑陋。

第二面试官们喜爱问的面试题就包含设计模式,如果把握这种设计模式,那你下一份工作的薪水可能就会高一点点。

第三你可能看过很多源码包含但不限于Mybatis、Spring ,他们的作者在编写代码的时候就充分利用了动静代理的思维,你把握了这个技术之后,就能很好的了解那些写框架的大佬们是怎么设计的框架,从而失去能力的晋升。

2. 动起来

2.1 先说代理

代理就是一个类代表另一个类提供性能,你能够了解成你朋友圈的微商。

厂商生产鞋子->微商从厂商那里零售鞋子在朋友圈进行售卖->你购买鞋子

微商就是代理,代理的就是鞋子厂商,而你就是那个应用鞋子厂商生产的鞋子然而你须要与微商打交道。

网上常常会看到一个UML图,在下也献丑画一个。

2.2 代理的优缺点

长处:我的总结就是高扩大、智能化、职责清晰

毛病:老本加大(你购买的鞋子可能变贵,运输工夫可能变长)

3. 先静再动

聊动静代理之前先写一个动态代理的例子。

package test;/** * @author 发现更多精彩  关注公众号:木子的昼夜编程 * 一个生存在互联网底层,做着增删改查的码农,不谙世事的造作 * @create 2021-10-16 9:39 * * 鞋厂标准 */public interface AShoeFactory {    /**     *     * @param name 购鞋者名字     * @param num 购买鞋子数量     */    void sellingShoes(String name, Integer num);}
package test;/** * @author 发现更多精彩  关注公众号:木子的昼夜编程 * 一个生存在互联网底层,做着增删改查的码农,不谙世事的造作 * @create 2021-10-16 9:44 * * 具体的鞋厂:鸿星尔克 */public class ErkeFactory implements AShoeFactory  {    @Override    public void sellingShoes(String name, Integer num) {        System.out.println(name+" 购买了 "+ num+" 双鞋,放烟花庆贺!!");    }}
package test;/** * @author 发现更多精彩  关注公众号:木子的昼夜编程 * 代理类:朋友圈某某某 */public class ProxyWechatMoments implements AShoeFactory{    public ProxyWechatMoments(){}    public ProxyWechatMoments(ErkeFactory erkeFactory){        this.erkeFactory = erkeFactory;    }    ErkeFactory erkeFactory;    @Override    public void sellingShoes(String name, Integer num) {        erkeFactory.sellingShoes(name, num);    }}

测试:

import test.ErkeFactory;import test.ProxyWechatMoments;/** * @author 发现更多精彩  关注公众号:木子的昼夜编程 */public class Test {    public static void main(String[] args) {        // 实在提供能力的类        ErkeFactory erkeFactory = new ErkeFactory();        // 代理类        ProxyWechatMoments proxy =  new ProxyWechatMoments(erkeFactory);        // 激动生产        proxy.sellingShoes("最最最最最小李子", 10);    }}

测试输入后果:

最最最最最小李子 购买了 10 双鞋,放烟花庆贺!!

4. 动起来

写了动态代理,动态代理实现比较简单。

毛病呢:扩大比拟麻烦,如果上述例子中再加一个匹克鞋厂,咱们就须要批改代码,会在代理类中用if else辨别要购买哪个牌子的鞋、

4.1 动静代理之 JDK
package test;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;/** * @author 发现更多精彩  关注公众号:木子的昼夜编程 * 动静代理类 */public class ProxyDynamicHandler implements InvocationHandler {    private  AShoeFactory shoeFactory;    public ProxyDynamicHandler(){}    public ProxyDynamicHandler(AShoeFactory shoeFactory) {        this.shoeFactory = shoeFactory;    }    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        // 卖鞋前后做的事件 是代理模式中常常用到的性能,作为加强和过滤应用        System.out.println("动静代理的益处,卖鞋前做一些事件");        String name = (String)args[0];        // 如果购买的人是 追忆流年时光 那我就不卖给他        if ("追忆流年时光".equals(name)) {            System.out.println("不卖, 谢谢 !");        } else {            // 这里用到了反射 没把握的人能够看我上一篇文章 或关注公众号:木子的昼夜编程            method.invoke(shoeFactory, args);        }        System.out.println("动静代理的益处,卖鞋后做一些事件");        return null;    }}
import sun.applet.AppletClassLoader;import test.AShoeFactory;import test.ErkeFactory;import test.ProxyDynamicHandler;import java.lang.reflect.Proxy;/** * @author 发现更多精彩  关注公众号:木子的昼夜编程 */public class TestDynamic {    public static void main(String[] args) {        AShoeFactory factory = (AShoeFactory) Proxy.newProxyInstance(                ErkeFactory.class.getClassLoader(),// 类加载器                ErkeFactory.class.getInterfaces(),// 代理的类的所有接口 Jdk动静代理是基于接口的                // 如果学过Spring的动静代理的话应该晓得,默认如果你的Service有接口Spring会应用Jdk动静代理                // 如果你的Service没有接口 Spring会应用CGLIB                // 这个常识 是我记忆中的 对不对不负责 哈哈                new ProxyDynamicHandler(new ErkeFactory()));        factory.sellingShoes("正义的帅哥", 10);        System.out.println("-------------------富丽丽的分割线------------------------");        factory.sellingShoes("追忆流年时光", 10);    }}

输入:

动静代理的益处,卖鞋前做一些事件
正义的帅哥 购买了 10 双鞋,放烟花庆贺!!
动静代理的益处,卖鞋后做一些事件
-------------------富丽丽的分割线------------------------
动静代理的益处,卖鞋前做一些事件
不卖, 谢谢 !
动静代理的益处,卖鞋后做一些事件

4.2 CGLIB 动静代理

CGLIB 是一个很牛X的代码生成库,常被用在一些AOP框架里。

CGLIB底层应用了ASM来操作字节码

他是对字节码进行了操作,说实话不是很平安,然而用起来很爽。

就是没有束缚的技术最疯狂。

CGLIB实现动静代理的形式就是认干爹,利用字节码批改性能创立一个被代理类(匹克鞋厂)的子类,提供性能的时候还是应用了被代理类的性能,就跟花钱找干爹一个情理

注: 这里的干爹是那种,70年代 80年代 很纯正的那种两家关系好 就认干爹那种 不是古代意思。

pom.xml

<dependencies>    <dependency>    <groupId>cglib</groupId>    <artifactId>cglib</artifactId>    <version>3.3.0</version>    </dependency></dependencies>
package test;/** * @author 发现更多精彩  关注公众号:木子的昼夜编程 */public class PeakFactory {    public void sellingShoes(String name, Integer num) {        System.out.println(name+" 购买了 "+ num+" 双匹克鞋,放烟花庆贺!!");    }}

自定义MethodHandler:

package test;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;/** * @author 发现更多精彩  关注公众号:木子的昼夜编程 */public class ProxyDynamicByCglib implements MethodInterceptor {    @Override    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {        // 卖鞋前后做的事件 是代理模式中常常用到的性能,作为加强和过滤应用        System.out.println("动静代理的益处,卖鞋前做一些事件");        String name = (String)args[0];        // 如果购买的人是 追忆流年时光 那我就不卖给他        if ("追忆流年时光".equals(name)) {            System.out.println("不卖, 谢谢 !");        } else {            System.out.println("看一下代理对象的父类是个啥:"+obj.getClass().getSuperclass());            // 调用业务类(父类)的办法            proxy.invokeSuper(obj, args);        }        System.out.println("动静代理的益处,卖鞋后做一些事件");        // 本次测试没有返回 无需返回        return null;    }}

测试:

import net.sf.cglib.proxy.Enhancer;import test.*;/** * @author 发现更多精彩  关注公众号:木子的昼夜编程 */public class TestDynamicCGLIB {    public static void main(String[] args) {        Enhancer enhancer = new Enhancer();        // 重点 设置理论提供办法的类为父类 Cglib应用本人的批改字节码性能 生成一个这个类的子类对象        enhancer.setSuperclass(PeakFactory.class);        enhancer.setCallback(new ProxyDynamicByCglib());// 自定义的Intrceptor        PeakFactory factory = (PeakFactory) enhancer.create();        factory.sellingShoes("正义的帅哥", 10);        System.out.println("-------------------富丽丽的分割线------------------------");        factory.sellingShoes("追忆流年时光", 10);    }}

输入:

动静代理的益处,卖鞋前做一些事件
看一下代理对象的父类是个啥:class test.PeakFactory
正义的帅哥 购买了 10 双匹克鞋,放烟花庆贺!!
动静代理的益处,卖鞋后做一些事件
-------------------富丽丽的分割线------------------------
动静代理的益处,卖鞋前做一些事件
不卖, 谢谢 !
动静代理的益处,卖鞋后做一些事件

5. 唠唠

代理的话我对JDK动静代理和CGLIB动静代理的底层理解不是很好,所以就只开展说了一下简略的利用。

其实大部分时候看架构源码,很多中央会用到代理模式,依据我的教训,会简略应用的就可以看懂架构中的代码流程,不必摸索太深,当然不是不激励你去摸索,常识说如果有工夫的话再去摸索,没工夫就先学会怎么用。

本文由博客一文多发平台 OpenWrite 公布!