返回介绍

7.5.3 织入

发布于 2025-04-22 22:09:14 字数 5942 浏览 0 评论 0 收藏

当我们完成了所有的 AspectJ 的准备工作后便可以进行织入分析了,首先还是从 LoadTimeWeaverAwareProcessor 开始。

LoadTimeWeaverAwareProcessor 实现 BeanPostProcessor 方法,那么对于 BeanPostProcessor 接口来讲,postProcessBeforeInitialization 与 postProcessAfterInitialization 有着其特殊意义,也就是说在所有 bean 的初始化之前与之后都会分别调用对应的方法,那么在 LoadTimeWeaverAwareProcessor 中的 postProcessBeforeInitialization 函数中完成了什么样的逻辑呢?

public Object postProcessBeforeInitialization(Object bean, String beanName) throws

BeansException {

  if (bean instanceof LoadTimeWeaverAware) {

   LoadTimeWeaver ltw = this.loadTimeWeaver;

   if (ltw == null) {

    Assert.state(this.beanFactory != null,

    "BeanFactory required if no LoadTimeWeaver explicitly

   specified");

    ltw = this.beanFactory.getBean(

   ConfigurableApplicationContext.LOAD_TIME_WEAVER_BEAN_NAME,

   LoadTimeWeaver.class);

  }

   ((LoadTimeWeaverAware) bean).setLoadTimeWeaver(ltw);

 }

  return bean;

}

我们综合之前讲解的所有信息,将所有相关信息串联起来一起分析这个函数。

在 LoadTimeWeaverAwareProcessor 中的 postProcessBeforeInitialization 函数中,因为最开始的 if 判断注定这个后处理器只对 LoadTimeWeaverAware 类型的 bean 起作用,而纵观所有的 bean,实现 LoadTimeWeaver 接口的类只有 AspectJWeavingEnabler。

当在 Spring 中调用 AspectJWeavingEnabler 时,this.loadTimeWeaver 尚未被初始化,那么,会直接调用 beanFactory.getBean 方法获取对应的 DefaultContextLoadTimeWeaver 类型的 bean,并将其设置为 AspectJWeavingEnabler 类型 bean 的 loadTimeWeaver 属性中。当然 AspectJWeavingEnabler 同样实现了 BeanClassLoaderAware 以及 Ordered 接口,实现 BeanClassLoaderAware 接口保证了在 bean 初始化的时候调用 AbstractAutowireCapableBeanFactory 的 invokeAwareMethods 的时候将 beanClassLoader 赋值给当前类。而实现 Ordered 接口则保证在实例化 bean 时当前 bean 会被最先初始化。

而 DefaultContextLoadTimeWeaver 类又同时实现了 LoadTimeWeaver、BeanClassLoaderAware 以及 DisposableBean。其中 DisposableBean 接口保证在 bean 销毁时会调用 destroy 方法进行 bean 的清理,而 BeanClassLoaderAware 接口则保证在 bean 的初始化调用 AbstractAutowireCapable BeanFactory 的 invokeAwareMethods 时调用 setBeanClassLoader 方法。

public void setBeanClassLoader(ClassLoader classLoader) {

  LoadTimeWeaver serverSpecificLoadTimeWeaver = createServerSpecificLoadTimeWeaver

 (classLoader);

  if (serverSpecificLoadTimeWeaver != null) {

   if (logger.isInfoEnabled()) {

    logger.info("Determined server-specific load-time weaver: " +

   serverSpecificLoadTimeWeaver.getClass().getName());

  }

   this.loadTimeWeaver = serverSpecificLoadTimeWeaver;

  }else if (InstrumentationLoadTimeWeaver.isInstrumentationAvailable()) {

  //检查当前虚拟机中的 Instrumentation 实例是否可用

   logger.info("Found Spring's JVM agent for instrumentation");

  this.loadTimeWeaver = new InstrumentationLoadTimeWeaver(classLoader);

  }else {

   try {

    this.loadTimeWeaver = new ReflectiveLoadTimeWeaver(classLoader);

    logger.info("Using a reflective load-time weaver for class loader: " +

   this.loadTimeWeaver.getInstrumentableClassLoader().

   getClass().getName());

  }

   catch (IllegalStateException ex) {

    throw new IllegalStateException(ex.getMessage() + " Specify a custom

    LoadTimeWeaver or start your " +

    "Java virtual machine with Spring's agent: -javaagent:org.

   Springframework.instrument.jar");

  }

 }

}

上面的函数中有一句很容易被忽略但是很关键的代码:

this.loadTimeWeaver = new InstrumentationLoadTimeWeaver(classLoader);

这句代码不仅仅是实例化了一个 InstrumentationLoadTimeWeaver 类型的实例,而且在实例化过程中还做了一些额外的操作。

在实例化的过程中会对当前的 this.instrumentation 属性进行初始化,而初始化的代码如下:this.instrumentation = getInstrumentation(),也就是说在 InstrumentationLoadTimeWeaver 实例化后其属性 Instrumentation 已经被初始化为代表着当前虚拟机的实例了。综合我们讲过的例子,对于注册转换器,如 addTransformer 函数等,便可以直接使用此属性进行操作了。

也就是经过以上程序的处理后,在 Spring 中的 bean 之间的关系如下:

AspectJWeavingEnabler 类型的 bean 中的 loadTimeWeaver 属性被初始化为 Default ContextLoadTimeWeaver 类型的 bean;

DefaultContextLoadTimeWeaver 类型的 bean 中的 loadTimeWeaver 属性被初始化为 InstrumentationLoadTimeWeaver。

因为 AspectJWeavingEnabler 类同样实现了 BeanFactoryPostProcessor,所以当所有 bean 解析结束后会调用其 postProcessBeanFactory 方法。

public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws

BeansException {

 enableAspectJWeaving(this.loadTimeWeaver, this.beanClassLoader);

}

public static void enableAspectJWeaving(LoadTimeWeaver weaverToUse, ClassLoader

beanClassLoader) {

  if (weaverToUse == null) {

//此时已经被初始化为 DefaultContextLoadTimeWeaver

  if (InstrumentationLoadTimeWeaver.isInstrumentationAvailable()) {

   weaverToUse = new InstrumentationLoadTimeWeaver(beanClassLoader);

 }

  else {

   throw new IllegalStateException("No LoadTimeWeaver available");

 }

}

//使用 DefaultContextLoadTimeWeaver 类型的 bean 中的 loadTimeWeaver 属性注册转换器

 weaverToUse.addTransformer(new AspectJClassBypassingClassFileTransformer(

  new ClassPreProcessorAgentAdapter()));

}

private static class AspectJClassBypassingClassFileTransformer implements Class

FileTransformer {

  private final ClassFileTransformer delegate;

public AspectJClassBypassingClassFileTransformer(ClassFileTransformer delegate) {

  this.delegate = delegate;

}

public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,

ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {

  if (className.startsWith("org.aspectj") || className.startsWith

  ("org/aspectj")) {

   return classfileBuffer;

 }

 //委托给 AspectJ 代理继续处理

  return this.delegate.transform(loader, className, classBeingRedefined,

  protectionDomain, classfileBuffer);

 }

}

AspectJClassBypassingClassFileTransformer 的作用仅仅是告诉 AspectJ 以 org.aspectj 开头的或者 org/aspectj 开头的类不进行处理。

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。