织入
当我们完成了所有的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,实现LoadTimeWeaverAware接口的只有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的初始化调用AbstractAutowireCapableBeanFactory的invokeAwareMethods时调用setBeanClassLoader方法。
public void setBeanClassLoader(ClassLoader classLoader) { LoadTimeWeaver serverSpecificLoadTimeWeaver = createServerSpecificLoadTimeWeaver(classLoader); if (serverSpecificLoadTimeWeaver != null) { if (logger.isDebugEnabled()) { logger.debug("Determined server-specific load-time weaver: " + serverSpecificLoadTimeWeaver.getClass().getName()); } this.loadTimeWeaver = serverSpecificLoadTimeWeaver; } else if (InstrumentationLoadTimeWeaver.isInstrumentationAvailable()) { logger.debug("Found Spring's JVM agent for instrumentation"); //检查当前虚拟机中的Instrumentation实例是否可用 this.loadTimeWeaver = new InstrumentationLoadTimeWeaver(classLoader); } else { try { this.loadTimeWeaver = new ReflectiveLoadTimeWeaver(classLoader); if (logger.isDebugEnabled()) { logger.debug("Using 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"); } } }
上述加红的代码不仅仅是实例化了一个InstrumentationLoadTimeWeaver类型的实例,而且在实例化过程中还做了一些额外的操作。
在实例化的过程中会对当前的this.instrumentation属性进行初始化,而初始化的代码如下:this.instrumentation = getInstrumentation(),也就是说在InstrumentationLoadTimeWeaver实例化后其属性Instrumentation已经被初始化为代表着当前虚拟机的实例了。
也就是经过以上程序处理后,在Spring中的bean之间的关系如下:
❤ AspectJWeavingEnabler 类型的 bean中的loadTimeWeaver属性被初始化为DefaultContextLoadTimeWeaver类型的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( @Nullable LoadTimeWeaver weaverToUse, @Nullable 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 ClassFileTransformer { private final ClassFileTransformer delegate; public AspectJClassBypassingClassFileTransformer(ClassFileTransformer delegate) { this.delegate = delegate; } @Override 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; } return this.delegate.transform(loader, className, classBeingRedefined, protectionDomain, classfileBuffer); } }
AspectJClassBypassingClassFileTransformer的作用仅仅是告诉AspectJ以org.aspectj开头的或者org/aspectj开头的类不进行处理。
参考:《Spring源码深度解析》 郝佳 编著: