浅谈代理模式

℡╲_俬逩灬. 提交于 2020-02-26 14:46:35

介绍

代理模式是一种非常好理解的设计面试:当前对象不愿意干的,没法干的东西委托给别的对象来做

用代码描述代理模式

一个程序员接口,他每天写代码

ndb也是一个程序员

静态代理

ndb想请一个程序员大V给自己点赞,已得到人气和money

透明代理(普通代理)

ndb想让程序员大v只做ndb的生意

代理类自定义方法

大v看到ndb赚大钱,决定加钱

动态代理

ndb 决定不请大v,而请水军(水军便宜,只要点赞就行)

public class Java3y implements Programmer {

    @Override
    public void coding() {
        System.out.println("Java3y最新文章:......给女朋友讲解什么是代理模式.......");
    }
}

动态代理

Java提供一个Proxy类,调用它的newinstance方法可以生成某个对象的地理对象,需要三个参数:

  • 参数一:生成代理对象使用哪个类装载器【一般我们使用的是被代理类的装载器】
  • 参数二:生成哪个对象,通过接口指定【指定要被代理类的接口】
  • 参数三:生成的代理对象的方法里干什么事【实现handler接口,我们想怎么实现就怎么实现】

在编写动态代理之前,要明确几个概念

  • 代理对象拥有目标对象相同的方法【参数二指定了对象的接口,代理对象会实现接口的所有方法】
  • 用户调用代理对象的什么方法,都是在调用处理器的invoke方法【被拦截】
  • 使用jdk动态代理必须要有接口【参数二日需要接口】
    上面也说了:代理对象会实现接口的所有方法,这些实现的方法交由我们的handler来处理
    所有通过动态代理实现的方法全部通过invoke()调用

image

动态代理的调用过程
image

静态代理和动态代理的区别

  • 静态代理需要自己写代理类–代理类需要实现与目标对象相同的接口
  • 而动态代理不需要自己编写代理类–动态生成

使用静态代理类时:
如果目标对象有很多方法的话,那我们还是得一一实现,比较麻烦

使用动态代理时:
代理对象的生成,时利用jdkapi,动态地在内存中构建代理对象(需要我们指定创建,代理对象/目标对象 实现的接口类型),并且默认实现接口的全部方法

典型应用

我们之前写过中文过滤器的时候,需要使用包装设计模式来设计一个request类,如果不是提供servlet提供了实现类给我们,我们使用包装设计模式会比较麻烦

现在我们学习了动态代理,动态代理就是拦截直接访问对象,可以给对象进行增强的一项功能,

中文过滤器

public void doFilter(final ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        final HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;

        response.setContentType("text/html;charset=UTF-8");
        request.setCharacterEncoding("UTF-8");


        //放出去的是代理对象
        chain.doFilter((ServletRequest) Proxy.newProxyInstance(CharacterEncodingFilter.class.getClassLoader(), request.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                //判断是不是getParameter方法
                if (!method.getName().equals("getParameter")) {

                    //不是就使用request调用
                   return method.invoke(request, args);
                }

                //判断是否是get类型的
                if (!request.getMethod().equalsIgnoreCase("get")) {
                   return method.invoke(request, args);
                }

                //执行到这里,只能是get类型的getParameter方法了。
                String value = (String) method.invoke(request, args);
                if (value == null) {
                    return null;
                }
                return new String(value.getBytes("ISO8859-1"), "UTF-8");
            }

        }), response);

    }

要实现动态代理必须要有接口,动态代理是基于接口来代理(实现接口的所有方法),如果没有接口的话,我们可以考虑cglib代理

cglib代理也叫做子类代理,从内存中创建出一个子类来拓展目标对象的功能

总的来说:代理模式是我们写代码中用得很多的一种模式了,Spring的AOP底层其实就是动态代理来实现的–>面向切面编程

其实只要记住一点:原有的对象需要额外的功能,想想动态代理这项技术!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!