篡改既存的jar包

    这一篇其实是接着《利用动态代理扩展类加载器的功能》这一篇的,因为都是在解决同一个问题。《利用动态代理扩展类加载器的功能》中说道通过动态代理生成ModuleClassLoader的代理对象,并通过 Thread.currentThread().setContextClassLoader(classLoaderProxy)修改调原本的类加载器。但是这样只能修改当前线程的类加载器,如果说代码中是通过Class.forName()这种方法,或者在其他线程中进行加载类,那还是不能走到我的自定义类加载器中。
    如果说在非当前线程中加载类的情况出现在我们自己的代码中,我们其实可以通过修改代码来解决,但是这个问题却出现在了依赖的jar包,这种情况就很头疼了。经过搜索和思考,对于这种情况大致有以下几种解决方案。

  1. 继承原jar包中的类(前提是该类不能为final),然后重写方法,在引用的地方通过setXXX的方法换成自己的子类。这种方法的局限性是,对jar包中类进行引用的地方,必须为我们自己的类,或者我们能够找到引用和创建的地点,通过反射的方法重新set我们的子类。这种方法的优点:代码侵入较少。缺点:原本的类不能是final,否则不能继承,另外必须找到该类使用的地方,如果有很多个的话,就显得比较麻烦了。

  2. 利用类加载器的性质,类加载器加载类文件的时候,会优先从当前项目目录找类,如果找不到再去找当前项目的lib目录下(也就是依赖jar包中)去找类,基于这个性质,我们可以在项目中创建一个包名,文件名,类名完全一致的类,然后将其中我们需要修改的地方进行修改。当类加载器进行加载类时,会先加载我们的这个类,然后就不会去jar包中找原本的类了。优点:修改成本和实现成本很低。缺点:一个项目中有多个一模一样的类,不利于未来的维护,容易挖坑。另外这个方法只适用于有目录层级的项目,如果你的项目jar包没有目录层级,那这个方法就不可能,因为你也不知道类加载器会先加载哪一个类。

  3. 究极武器ASM,可能大家没听说过ASM,是一种动态生成和修改java的class类的框架。挺起来感觉陌生,我们实现动态代理有两种方式Enhancer.create()和Proxy.newProxyInstance(),Proxy.newProxyInstance()基于java的代理类,而Enhancer.create()则是基于asm通过动态修改类文件实现的动态代理。这就是为什么Enhancer.create()可以作用于类,而Proxy.newProxyInstance()只能作用于接口的原因。优点:无所不能。缺点:需要较大的学习成本,也可以使用一些封装过的jar包。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值