• 双亲委派机制的一个应用


    问题背景

    遇到一个问题:业务异常了,抛出ApiException。工程代码里没有打印error,日志中却发现了error日志(我们的业务异常不允许打印error日志,因为error日志会产生告警,而业务异常不应告警)。经排查,是org.apache.catalina.core.StandardWrapperValve类中捕获了ServletException,打印了error异常。

    解决方案

    这里我们看到,紧急是apache.catalina的源码打印日志级别的问题。自然想到就是能在捕获异常的地方,区分下是不是ApiException,如果是则打印info日志,如果不是,还是按原来的方式打印error日志。
    涉及到改源码,改了如何生效呢?
    1、下载整个jar的源码,改了源码,然后编译成新的jar,替换。【过程复杂,且不好维护,放弃】
    2、在工程下,创建个类:org.apache.catalina.core.StandardWrapperValve,修改StandardWrapperValve源码,然后利用类加载机制将修改后的源码加载到jvm中,老的源码就不会加载了。

    双亲委派

    为什么可以用方案2这种方式呢?回顾下双亲委派机制

    当一个类(我们自己写的或者Apache等三方框架的)文件要被加载时。不考虑我们自定义类加载器,首先会在AppClassLoader中检查是否加载过,如果有那就无需再加载了。如果没有,那么会拿到父加载器,然后调用父加载器的loadClass方法。父类中同理也会先检查自己是否已经加载过,如果没有再往上。注意这个类似递归的过程,直到到达Bootstrap classLoader之前,都是在检查是否加载过,并不会选择自己去加载。直到BootstrapClassLoader,已经没有父加载器了,这时候开始考虑自己是否能加载了,如果自己无法加载,会下沉到子加载器去加载,一直到最底层,如果没有任何加载器能加载,就会抛出ClassNotFoundException。

    如何确定被加载过了呢?
    JVM加载过的内缓存起来,类似放在Map中。jvm中类相同的条件:类加载器实例+包名+类名。显然我们写的StandardWrapperValve和Apache catalina的StandardWrapperValve类加载器都是AppClassLoader,并且包名和类名都是一样的。所以只要保证JVM先加载我们改写过的StandardWrapperValve,JVM就不会去加载Apache catalina的StandardWrapperValve了

  • 相关阅读:
    idea 字体大小设置
    idea单窗口管理多个工程项目
    java迭代器使用(修改元素的值)
    idea自动保存设置+确保修改正确
    服务器暂时无法处理您的请求,请稍后重试。解决方法
    [C#] IpcChannel双向通信,参考MAF的AddInProcess开发插件,服务断开重新打开及服务生存周期管理
    XE10.4.2 IDE关闭LSP
    delphi 色彩搭配,HSV与RGB转换
    金额转大写 (delphi)
    MMDet 踩坑
  • 原文地址:https://www.cnblogs.com/zhangxianming/p/15581559.html
Copyright © 2020-2023  润新知