读书人

Spring之LoadTimeWeaver一个需求挑

发布时间: 2012-09-07 10:38:15 作者: rapoo

Spring之LoadTimeWeaver——一个需求引发的思考

最近有个需求——记录应用中某些接口被调用的轨迹,说白了,记录下入参、出参等即可。

?

?

public class DemoBean {    public void run() {       System.out.println("Run");    }}
???

接着,我们编写分析方法执行效率的切面。

?

@Aspectpublic class ProfilingAspect {    @Around("profileMethod()")    public Object profile(ProceedingJoinPoint pjp) throws Throwable {       StopWatch sw = new StopWatch(getClass().getSimpleName());       try {           sw.start(pjp.getSignature().getName());           return pjp.proceed();       } finally {           sw.stop();           System.out.println(sw.prettyPrint());       }    }    @Pointcut("execution(public * com.shansun..*(..))")    public void profileMethod() {}}

?

?

<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd"><aspectj>    <weaver>       <include within="com.shansun..*" />    </weaver>    <aspects>       <!-- weave in just this aspect -->       <aspect name="com.shansun.multidemo.spring.ltw.ProfilingAspect" />    </aspects></aspectj>

?

?

<?xml version="1.0" encoding="GBK"?> <beans xmlns="http://www.springframework.org/schema/beans"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"    xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"    xsi:schemaLocation="        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">    <context:load-time-weaver aspectj-weaving="autodetect" />     <context:component-scan base-package="com.shansun.multidemo"></context:component-scan></beans>

?

通过 <context:load-time-weaver ?aspectj-weaving="on" /> 使 spring 开启loadtimeweaver, 注意 aspectj-weaving 有三个选项 : on,off, auto-detect,?如果设置为 auto-detect, spring 将会在 classpath中查找 aspejct 需要的 META-INF/aop.xml, 如果找到则开启aspectj weaving, 这个逻辑在LoadTimeWeaverBeanDefinitionParser#isAspectJWeavingEnabled 方法中:

protected boolean isAspectJWeavingEnabled(String value, ParserContext parserContext) {       if ("on".equals(value)) {           return true;       }       else if ("off".equals(value)) {           return false;       }       else {           // Determine default...           ClassLoader cl = parserContext.getReaderContext().getResourceLoader().getClassLoader();           return (cl.getResource(ASPECTJ_AOP_XML_RESOURCE) != null);       }}

?

?

public class Main {    public static void main(String[] args) {        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");//      DemoBean bean = (DemoBean) ctx.getBean("demoBean");        DemoBean bean = new DemoBean();        bean.run();    }}

??

?

????????

?

输出结果如下:

Run

StopWatch'ProfilingAspect': running time (millis) = 0

-----------------------------------------

ms???? %????Task name

-----------------------------------------

?

Exception in thread "main" java.lang.IllegalStateException: Must start with Java agent to use InstrumentationLoadTimeWeaver. See Spring documentation.    at org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver.addTransformer(InstrumentationLoadTimeWeaver.java:88)    at org.springframework.context.weaving.AspectJWeavingEnabler.postProcessBeanFactory(AspectJWeavingEnabler.java:69)    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:553)    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:536)    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:362)    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)    at com.shansun.multidemo.spring.Main.main(Main.java:25)

?

public void addTransformer(ClassFileTransformer transformer) {       Assert.notNull(transformer, "Transformer must not be null");       FilteringClassFileTransformer actualTransformer =              new FilteringClassFileTransformer(transformer, this.classLoader);       synchronized (this.transformers) {           if (this.instrumentation == null) {              throw new IllegalStateException(                     "Must start with Java agent to use InstrumentationLoadTimeWeaver. See Spring documentation.");           }           this.instrumentation.addTransformer(actualTransformer);           this.transformers.add(actualTransformer);       }}

?

?

?

public class ExtInstrumentationLoadTimeWeaver extends        InstrumentationLoadTimeWeaver {     @Override    public void addTransformer(ClassFileTransformer transformer) {       try {           super.addTransformer(transformer);       } catch (Exception e) {}    }}
?

???

?

?

<?xml version="1.0" encoding="GBK"?> <beans xmlns="http://www.springframework.org/schema/beans"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"    xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"    xsi:schemaLocation="        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">    <context:load-time-weaver weaver-aspectj-weaving="autodetect" />     <context:component-scan base-package="com.shansun.multidemo"></context:component-scan></beans>
?

?

再次运行我们的main方法,发现只输出了如下结果,切面没有起作用。

Run

?

看到了么,同一份代码、同一份配置,只需要在VM启动参数中稍加变化,即可实现同一个应用包在不同环境下可以自由选择使用使用AOP功能。文章开头提到的那个需求也就迎刃而解了。

?

这只是一种解决途径,相信大家会有更好的方案。如果有,请您告诉我。J

?

参考文档:

1、使用AspectJLTW(Load Time Weaving)

2、Spring LoadTimeWeaver 的那些事儿

3、在Spring应用中使用AspectJ

?

1 楼 littleJava 2011-08-22 Instrumentation 和 javassist根据定义的加载规则,就可以实现了,原理也是aop 2 楼 hyaci2011 2011-11-04 Aspectj 难道 就不能单独支持 LTW ?一定要和spring 整合在一起..很纠结呀..
楼上的 解释一下 instrumentation ..我学习一下.

读书人网 >软件架构设计

热点推荐