JavaWeb基础知识day18——类加载器&静态代理&动态代理【jdk动态代理和cglib动态代理】

58 篇文章 0 订阅
28 篇文章 0 订阅

类加载器

类加载器:(了解)
    类加载:
        我们编写的.java文件,jvm会将变成.class文件.该文件要想运行,必须加载内存中,然后会生成一个对象.Class对象
    类加载器的作用:ClassLoader的具体作用就是将class文件加载到jvm虚拟机中去,程序就可以正确运行了。但是,jvm启动的时候,并不会一次性加载所有的class文件,而是根据需要去动态加载。想想也是的,一次性加载那么多jar包那么多class,那内存不崩溃。

ClassLoader:是一个抽象类。public abstract class ClassLoader {...}
    类加载器层次结构
        引导类加载器    【BootstrapClassLoader】:rt.jar         Bootstrap Loader(引导类加载器)是用非Java语言实现的【Bootstrap ClassLoader是由C/C++编写的,它本身是虚拟机的一部分,所以它并不是一个JAVA类】,无法获取到该加载器,所以才返回null。
        扩展类加载器【ExtClassLoader】:    ext/*.jar
        应用类加载器【AppClassLoader】:    我们自己编写类
启动类加载器、扩展类加载器、应用类加载以及自定义类加载器之间不存在继承关系。
    全盘负责委托机制【父委托机制】:
        当一个类运行的时候,有可能有其他类,应用类加载器询问扩展类加载器:你加载过这些类吗?
        扩展类加载器在向上问(引导类加载器):你加载过这些类吗?
        引导类加载器:我查查,有一个是我负责,我加载.
        扩展类加载器:接下来我来查,有几个是我负责,我加载,还有几个类我已经加载完成了,你可以直接使用
        应用类加载器:收到了 剩下的我来

JVM类加载的特点——双亲委派机制
双亲委派,类加载器会先让父类加载器加载类,只有所有的父类加载器都无法加载该类的时候,才会自己加载类。
AppClassLoader加载类时,会先把加载请求委派给父类加载器ExtClassLoader。ExtClassLoader加载类,会先把类加载请求委派给父类加载器BootStrapClassLoader。如果BootStrapClassLoader类加载器加载失败,才会使用ExtClassLoader类加载来加载;如果ExtClassLoader类加载器也加载失败,才会使用AppClassLoader类加载器来加载如果AppClassLoader类加载器也加载失败,由于在类加载器层次结构中已经没有其他的子加载器了,所以只能报出异常ClassNotFoundException。

双亲委派机制的意义:
保证每个类只被加载过一次



静态代理和动态代理

静态代理书写步骤:
1.要求被装饰者和装饰者实现同一个接口或者继承同一个类
2.在装饰者中要有被装饰者的引用
3.对需要加强的方法进行加强
4.对不需要加强的方法调用原来的方法

动态代理:
在项目运行的时候才创建一个代理对象,对方法进行增强(控制)
方式1:
    jdk中Proxy类,前提:实现接口
方式2:
    spring中cglib,前提:继承类
    
Proxy是一个Java类:    static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h):静态newProxyInstance 方法
InvocationHandler是一个接口。代理对象用来处理该如何处理的业务逻辑。
动态的在内存中创建一个代理对象    
    static Object Proxy.newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h) 
        参数说明:
            ClassLoader:代理对象类加载器 一般我们使用的是被代理对象的类加载器
            Class[]:代理对象需要实现接口 一般我们使用的是被代理对象所实现的所有接口
            InvocationHandler:执行处理类.在这里面对方法进行加强

        InvocationHandler【接口】中只有一个方法
            Object invoke(Object proxy, Method method, Object[] args) 
                参数说明:
                    proxy:代理对象
                    method:当前执行的方法
                    args:当前方法执行的时候所需要的参数
                    返回值:就是当前method对象执行的返回值

案例一:
public static void main(String[] args) {
		final QQ qq=new QQ();
		//创建代理对象
		Car qqProxy=(Car) Proxy.newProxyInstance(QQ.class.getClassLoader(), new Class[]{Car.class}, new InvocationHandler() {
			@Override
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
				//对所有方法进行加强
				/*System.out.println("加上电池");
				Object obj = method.invoke(qq, args);
				System.out.println("5秒破百");
				return obj;*/
				//只对run方法进行加强
				if("run".equals(method.getName())){
					System.out.println("加上电池");
					Object obj = method.invoke(qq, args);
					System.out.println("5秒破百");
					return obj;
				}
				return method.invoke(qq, args);
			}
		});
		qqProxy.run();
		qqProxy.stop();
	}


案例二:统一编码解决乱码
public class EncodingFilter implements Filter {
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {

	}
	@Override
	public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
			throws IOException, ServletException {
		//1.强转
		final HttpServletRequest request=(HttpServletRequest) req;
		HttpServletResponse response=(HttpServletResponse) resp;				
		//创建代理对象
		HttpServletRequest requestProxy=(HttpServletRequest) Proxy.newProxyInstance(HttpServletRequest.class.getClassLoader(), request.getClass().getInterfaces(), new InvocationHandler() {			
			@Override
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
				if("getParameter".equals(method.getName())){
					//获取请求方式
					String m = request.getMethod();
					
					if("get".equalsIgnoreCase(m)){
						String s = (String) method.invoke(request, args);//相当于  request.getParameter(args);
						return new String(s.getBytes("iso8859-1"),"utf-8");
					}else if("post".equalsIgnoreCase(m)){
						request.setCharacterEncoding("utf-8");
						return method.invoke(request, args);
					}
				}				
				//不需要加强的方法
				return method.invoke(request, args);
			}
		});		
		//2.放行
		chain.doFilter(requestProxy, response);		
	}
	@Override
	public void destroy() {

	}
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值