创建AOP静态代理(下篇)

织入

当我们完成了所有的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源码深度解析》 郝佳 编著:

原文地址:https://www.cnblogs.com/Joe-Go/p/10244469.html