动态代理

第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文件加载多次

原文地址:https://www.cnblogs.com/shan1393/p/9174087.html