• 动态代理


    第1章 使用动态代理解决网站的字符集编码

    1.1 介绍

    学习过滤器时,我们使用“装饰者”对request进行增强,从而使getpost使用 request.getParameter()获得的数据都没有乱码。本案例我们将使用一个全新的技术动态代理,对“统一GETPOST乱码”案例进行重写。

     //创建一个与代理对象相关联的InvocationHandler
      InvocationHandler stuHandler = new MyInvocationHandler<Person>(stu);
    //创建一个代理对象stuProxy,代理对象的每个执行方法都会替换执行Invocation中的invoke方法
      Person stuProxy= (Person) Proxy.newProxyInstance(Person.class.getClassLoader(), new Class<?>[]{Person.class}, stuHandler);

    1.2 相关知识点:Proxy

    l Proxy.newProxyInstance    三个参数

    参数1loader ,类加载器,动态代理类运行时创建,任何类都需要类加载器将其加载到内存。

    一般情况:当前类.class.getClassLoader();

    参数2Class[] interfaces 代理类需要实现的所有接口

    方式1:目标类实例.getClass().getInterfaces();

    注意:只能获得自己接口,不能获得父元素接口

    方式2new Class[]{UserService.class}   

    例如:jdbc 驱动  --> DriverManager  获得接口 Connection

    参数3InvocationHandler  处理类,接口,必须进行实现类,一般采用匿名内部

    提供 invoke 方法(以下三个参数)代理类的每一个方法执行时,都将调用一次invoke

    参数31Object proxy :代理对象

    参数32Method method : 代理对象当前执行的方法的描述对象(反射)

    执行方法名:method.getName()

    执行方法:method.invoke(对象,实际参数)

    参数33Object[] args :方法实际参数

    1.1 案例实现

    @WebFilter("/*")

    public class EncodingFilter implements Filter {

     

    @Override

    public void init(FilterConfig filterConfig) throws ServletException {

     

    }

     

    @Override

    public void doFilter(ServletRequest req, ServletResponse response, FilterChain chain)

    throws IOException, ServletException {

     

    final HttpServletRequest request = (HttpServletRequest) req;

     

    HttpServletRequest requestProxy = (HttpServletRequest)Proxy.newProxyInstance(

    EncodingFilter.class.getClassLoader(),

    new Class[]{HttpServletRequest.class},

    new InvocationHandler() {

    @Override

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

    if("get".equals(request.getMethod())) {

    //对指定方法进行增强

    if("getParameter".equals(method.getName())){

    // 执行方法获得返回值

    String value = (String) method.invoke(request, args);

    return new String(value.getBytes("UTF-8") , "UTF-8");

    }

    }

    //放行

    return method.invoke(request, args);

    }

    });

    //放行

    chain.doFilter(requestProxy, response);

     

    }

     

    @Override

    public void destroy() {

     

    }

     

    }

     

     

    使用 .class.getClassLoader()  获得加载自己的类加载器

    l 类加载器加载机制:全盘负责委托机制

    全盘负责:A类如果要使用B类(不存在),A类加载器C必须负责加载B类。

    委托机制:A类加载器如果要加载资源B,必须询问父类加载是否加载。

    如果加载,将直接使用。

    如果没有机制,自己再加载。

    采用 全盘负责委托机制 保证 一个class文件 只会被加载一次,形成一个Class对象。

    l 注意:

    如果一个class文件,被两个类加载器加载,将是两个对象。

    提示 com.itheima.Hello  不能强制成 com.itheima.Hello

                  h.getClass() -->A                 h.getClass()  -->B

    自定义类加载,可以将一个class文件加载多次

  • 相关阅读:
    Python的单元测试(二)
    Python的单元测试(一)
    未知道——广场式的真匿名交流网站(一)
    xpath提取多个标签下的text
    清空Github上某个文件的历史版本
    如何正确使用日志Log
    使用AWS亚马逊云搭建Gmail转发服务(三)
    玩转Windows服务系列——Windows服务小技巧
    玩转Windows服务系列——服务运行、停止流程浅析
    玩转Windows服务系列——无COM接口Windows服务启动失败原因及解决方案
  • 原文地址:https://www.cnblogs.com/shan1393/p/9174087.html
Copyright © 2020-2023  润新知