Spring LoadTimeWeaver 详解

来源:互联网 发布:搞笑小黄鸡软件下载 编辑:程序博客网 时间:2024/06/06 01:28
 spring load time weaver 主要通过以下步骤完成 : 

   1. 在启动程序的 jvm argument 中增加 spring-agent.jar 以获得 jvm 导出的 instrumentation 
   2. aspectj 拦截 domain object 的创建 

   3. 在 AnnotationBeanConfigurerAspect 中完成对 domain object 的注入 

1. Add spring-agent.jar to jvm argument 
   
   如果是命令行启动, 使用 java -javaagent:#{your path}/spring-agent.jar MyProgram 命令启动程序, 如果是 ide, 在 jvm argument 中增加 -javaagent:#{your path}/spring-agent.jar 即可. 

   增加这个参数的目的就是获取 jvm 导出的 instrumentation 引用以便后续操作的进行, 打开 spring-agent.jar 的 META-INF/MENIFEST.MF 会发现其中一句 : Premain-Class: org.springframework.instrument.InstrumentationSavingAgent, 没错, 根据 instrumentation 规范, Premain-Class 就是用于处理 instrumentation 的入口, 事实上 spring-agent.jar 里也只有这一个 class, 打开代码会发现非常简单 : 

public class InstrumentationSavingAgent {private static volatile Instrumentation instrumentation;/** * Save the {@link Instrumentation} interface exposed by the JVM. */public static void premain(String agentArgs, Instrumentation inst) {instrumentation = inst;}}

在 premain 方法里将 instrumentation 保存到 static 引用中以便后续访问.

2. 配置 spring 支持 load time weaver 

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);}}

@Configurable(autowire = Autowire.BY_TYPE)  public class User {            @Resource      // 或使用 @Autowired      private UserRepository userRepository;            public void save() {          userRepository.save(this);      }    }  

4. 将 spring-agent.jar, spring-aspects.jar, aspectj-weaver.jar, aspectj-rt.jar 加入到 classpath 中, 运行期主要发生以下调用 : 

  • LoadTimeWeaverBeanDefinitionParser (spring.jar) // 解析配置
  • ->  AspectJWeavingEnabler (spring.jar) // 开启 aspectj weaving
  • ->  InstrumentationSavingAgent (spring-agent.jar)  // 获取 instrumentation
  • ->  InstrumentationLoadTimeWeaver#addTransformer (spring.jar) // 增加 aspectj class transformer 到 instrumentation
  • ->  ClassPreProcessorAgentAdapter#transform (aspectj-weaver.jar) // aspectj 拦截 domain object 装载
  • ->  AnnotationBeanConfigurerAspect#configureBean (spring-aspects.jar) // spring 注入依赖到标注了 @Configurable 的对象中
至此完成整个 load time weave 过程. 
注意前文中的 <context:annotation-config /> 并不是必须的, 如果不配置, userRepository 就不能用 annotation(@Resource 或 @Autowired) 注入而必须使用 set 方法. 


0 0
原创粉丝点击