Tomcat 7中配置AspectJ的Load Time weaving

最近项目中有个同事启用了AspectJ的Load Time Weaving,通过在Maven中打包部署在Weblogic完全没问题,但是在我的Tomcat 7中无法启动应用的情况,会出现类似“Can't Add Transfomer”以及采用-javaagent:spring-instructment.jar来避免该错误的提示,导致每次出现问题时,只能通过maven打包部署或者事先在代码加入日志来定位问题,极度不爽。

在使用Google大神在StackOverflow上找了一堆文章查看后发现两种解决方案:
1)通过配置在启动tomcat的脚本中配置-javaagent:spring-instrument.jar来解决。spring-instrument.jar在Spring各版本中名称不一样。在项目使用的最新的Spring4.0.2中名称为:spring-instrument-4.0.2.RELEASE.jar。在早期的spring版本中可能是spring-ageng.jar。发现通过设置该属性在tomcat7中完全不起作用。

2)通过将spring-instrument-tomcat-4.0.2.RELEASE.jar的jar包放置在Tomcat安装目录的lib下,同时将context.xml文件,文件内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<Context>
		<Loader loaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader"/>
</Context>

放置在Web项目的root目录(webapp或者WebContent目录,也就是与WEB-INF目录平行)下。在使用Eclipse自带的Server插件可以成功启动项目。
如果放置在TOMCAT安装目录的conf目录的context.xml文件(该文件的配置信息将对Tomcat中所有的web app起作用)中,发现启动项目仍然会出现上述错误。

由于在开发项目的过程中一直sysdeo的Tomcat插件,想通过该插件来启动web项目,发现还是抛出了上述错误。为什么要使用这个插件?因为这个插件比起自身的Eclipse的插件有很多好处,启动快速,不需要发布文件(因为直接加载编译好的class文件),修改文件不重启。经发现tomcat7一直采用自身的WebappClassLoader来加载class文件而不是上述配置的TomcatInstrumentableClassLoader来加载,初步怀疑可能是sysdeo的tomcat插件的DevLoader类实现无法识别上述的配置的类TomcatInstrumentableClassLoader,而采用Tomcat默认的WebappClassLoader类。

查看了DevLoader类的实现发现该类继承了WebappLoader,结合了 《深入剖析Tomcat 》第8章 Loader 这篇文章,发现WebappLoader类中实例化了WebappClassLoader。
现在目标就很明确了,只要让WebappLoader类中采用TomcatInstrumentableClassLoader而不是Tomcat默认的WebappClassLoader。需要将spring-instrument-tomcat-4.0.2.RELEASE.jar包放置在Tomcat安装目录的lib下,否则加载不到TomcatInstrumentableClassLoader类。
下载tomcat7对应版本的源代码,找到WebappLoader类将
private String loaderClass =
        "org.apache.catalina.loader.WebappClassLoader";
修改为
private String loaderClass =
        "org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader";
,重新编译该类,将该类的class文件替换到Tomcat安装目录下的catalina.jar即可。编译WebappClassLoader需要依赖:
catalina.jar
tomcat-coyote.jar
tomcat-util.jar
tomcat-juli.jar
其中最后一个jar包在bin目录下,而不是在lib目录下。
附件为:apache-tomcat-7.0.52的catalina.jar(WebappLoader.class文件loaderClass属性已更新为org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader)

最后,祝各位喜欢折腾的朋友好运。

你可能感兴趣的:(spring,aspectj,tomcat7)