- 前言
- 第一部分 核心实现
- 第 1 章 Spring 整体架构和环境搭建
- 第 2 章 容器的基本实现
- 第 3 章 默认标签的解析
- 第 4 章 自定义标签的解析
- 第 5 章 bean 的加载
- 第 6 章 容器的功能扩展
- 第 7 章 AOP
- 第二部分 企业应用
- 第 8 章 数据库连接 JDBC
- 第 9 章 整合 MyBatis
- 第 10 章 事务
- 第 11 章 SpringMVC
- 第 12 章 远程服务
- 第 13 章 Spring 消息
7.5.3 织入
当我们完成了所有的 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 开头的类不进行处理。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论