对开源软件修改的一些思考和总结
1.为什么修改?
公司需要开发一款基于web页面的报表应用,但是不能自己从零开发,要基于现有的开源框架进行二次开发或者如果开发框架能满足需求就不再进行二次开发。最后在github上找到一款基于java spring框架的报表软件,但是部分功能不满足目前的需求,需要进行二次开发。
2.如何修改最合适?
虽然进行二次开发,领导要求做到不能影响到后续的开源应用升级。也就是说,我们可以对源码进行二次开发,但是我们开发所做的修改不能影响到后续开源应用升级时代码的合入!这对于我们而言可就是有点难了,原因在于:我们要把这个源码的运行原理了解清楚已属不易,了解了原理之后要修改最快的方式当然是在源码中直接修改原有逻辑,但是要不影响升级,就需要一番巧妙的设计才行。
3. 修改的实现!
既然任务已经下达,我们就只有迎难而上了。在开发之前我先进行了一番思考了。第一,这类问题以前肯定有人遇到过,那么他们是怎么解决的?我想到了MyBatis开源框架中对于api接口实现查询的代理原理。就是一种典型的修改某个方法的实现逻辑,于是我明白了这就是java 设计模式中的代理模式。第二,代理的具体实现。我采用了最原始的xml配置的方式进行aop配置,生成切面,指定切点,生成around增强(因为要修改原有的逻辑),如果符合修改的条件就执行新的逻辑否则执行旧有逻辑。当然中间遇到一些问题更加加深了我对spring aop的认识。1.同一个类的实例的方法内再调用其他方法,不能出发代理。这时候就要修改aop的配置和源码的一些调用修改,aop的配置就是要将expose-proxy设置为true,然后在原先调用的地方改为AopContext.currentProxy()的方式。原因就是代理的是一个类的实例,如果不是通过该类的调用不会被代理的。通过以上配置就是会将代理类暴漏出去,然后直接使用代理类显性的调用方法。2.对于一些没有使用接口的类的方法的修改要将aop的配置改为proxy-target-class=true。原因是spring的aop底层实现有两种,一种是基于jdk的动态代理,一种是基于cglib的动态代理。两者的区别在于,前者适用于有接口实现的类的代理,后者可以代理那些没有接口实现的类的代理,因为后者是基于字节码框架,生成一个子类进而重写父类的方法。
4.总结
当我们遇到一些开发的难题的时候,首先要想这个问题以前的人有没有遇到过,他们是怎么解决的,我能使用他们的方法解决我的问题吗?其次,要对源码进行学习,并想为什么源码要这么设计,有什么好处,有什么坏处,以后在什么情况下能用这个设计呢;最后,熟练掌握设计模式对于我们设计和开发中解决关键问题的架构是大有裨益的。