动态代理
We are here to put a dent in the universe
动态代理
定义+分类:动态的给接口的实现类生成一个代理对象;
- 委托类[被代理的类]委托代理类实现相关的功能,从而实现了隐藏委托类。
静态代理+动态代理 ;基于接口实现的,如果当前类没有实现接口,不能给这个类进行代理- 使用关键字:Proxy
- 【注意:】代理的是接口的实现类对象
功能:
![]()
优缺点:
可以隐藏委托类的实现
- 可以实现委托类与实现客户之间的解耦,在不修改委托类的情况下,增强委托类的方法;
实现:JDK中的动态代理:Proxy对象
- Proxy.newProxyInstance
- ClassLoader:类加载器
- ,Class[]:被增强的对象的所有接口
- ,InvocationHandler:处理类【只有invoke()方法】
- 生成动态代理对象:Proxy.Proxy.newProxyInstance(ClassLoader,Class[],InvocationHandler)
- 在调用代理对象的所有方法的时候,InvocationHandler中的invoke()都会执行
- invoke(Object proxy,Method method ,Object[] params)
- 执行method().invoke()方法等同于被代理对象的方法执行
- 得到的代理对象,不能强转成某个具体的实现类
- 动态代理在开发中的应用:
- Spring框架【AOP底层实现就是使用代理机制,】
- 进行事物的管理,
- 增强类中的方法
- 类加载器:
- 把class字节码问价加载到JVM虚拟机中去运行。
- 在Java开发中类加载器的分类:
- 最高级别的类加载器:引导类加载器【底层是C/C++语言实现的】、/JABA_HOME/jre/lib/rt.jat,常用类
- 其次是扩展类加载器:Sun公司提供的类,不常用,得用扩展类加载器去加载;/JABA_HOME/jre/lib/ext/*.jar
- 最低级别的是应用类加载器:自己写的类,使用应用类加载器来来执行
- 加载原理:委托机制,
- 如何保证类只被加载一次:全盘机制,委托上一级,加载的时候从上之下加载,即引导类加载器加载完成之后,将剩下的抛给扩展类,最后抛给应用类加载器。
扩展【使用动态代理实现全站乱码处理】:
- 技术分析
- 继承:能控制这个类的结构
- 装饰者模式:增强的类和被增强的类实现相同的接口,增强的类中获得被增强的类的引用,接口中方法过多,需要增强所有的方法太麻烦
- 动态代理:被增强的类实现了接口
“`Java
//需求分析:
/*
在请求过程中【get/post】方式请求乱码的处理
@WebFilter(urlPatterns=”/*”)
public class GenericEncodingFilter implements Filter {@Override
public void init(FilterConfig filterConfig) throws ServletException {}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
final HttpServletRequest req = (HttpServletRequest) request;
// 增强req:
HttpServletRequest myReq = (HttpServletRequest) Proxy.newProxyInstance(req.getClass().getClassLoader(),
req.getClass().getInterfaces(), new InvocationHandler() {@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 判断执行的方法是否是getParameter: if("getParameter".equals(method.getName())){ // 调用的是getParameter:需要增强这个方法. // 判断请求方式是GET还是POST: String type = req.getMethod(); if("get".equalsIgnoreCase(type)){ String value = (String) method.invoke(req, args); value = new String(value.getBytes("ISO-8859-1"),"UTF-8"); return value; }else if("post".equalsIgnoreCase(type)){ req.setCharacterEncoding("UTF-8"); } } return method.invoke(req, args); } }); chain.doFilter(myReq, response);
}
@Override
public void destroy() {}
}