前面我们已经探讨过基于spring的动态aop处理 spring动态aop处理 spring同时也遵循了aop的标准,提供了静态aop的处理方式。
spring的配置增加如下配置开启静态aop:

 <context:load-time-weaver/>

可以看到,这里对应的schema是context,我们在spring-context模块下META-IUNF/spring.handlers中发现内容如下:

http\://www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler
http\://www.springframework.org/schema/jee=org.springframework.ejb.config.JeeNamespaceHandler
http\://www.springframework.org/schema/lang=org.springframework.scripting.config.LangNamespaceHandler
http\://www.springframework.org/schema/task=org.springframework.scheduling.config.TaskNamespaceHandler
http\://www.springframework.org/schema/cache=org.springframework.cache.config.CacheNamespaceHandler

其中context对应处理类为:org.springframework.context.config.ContextNamespaceHandler

public class ContextNamespaceHandler extends NamespaceHandlerSupport {@Overridepublic void init() {registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());}}

load-time-weaver解析类为: LoadTimeWeaverBeanDefinitionParser.解析逻辑主要集中在doParse方法中:


protected String getBeanClassName(Element element) {if (element.hasAttribute(WEAVER_CLASS_ATTRIBUTE)) {return element.getAttribute(WEAVER_CLASS_ATTRIBUTE);}return DEFAULT_LOAD_TIME_WEAVER_CLASS_NAME;}@Overrideprotected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext) {return ConfigurableApplicationContext.LOAD_TIME_WEAVER_BEAN_NAME;}protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);if (isAspectJWeavingEnabled(element.getAttribute(ASPECTJ_WEAVING_ATTRIBUTE), parserContext)) {if (!parserContext.getRegistry().containsBeanDefinition(ASPECTJ_WEAVING_ENABLER_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(ASPECTJ_WEAVING_ENABLER_CLASS_NAME);parserContext.registerBeanComponent(new BeanComponentDefinition(def, ASPECTJ_WEAVING_ENABLER_BEAN_NAME));}if (isBeanConfigurerAspectEnabled(parserContext.getReaderContext().getBeanClassLoader())) {new SpringConfiguredBeanDefinitionParser().parse(element, parserContext);}}}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().getBeanClassLoader();return (cl != null && cl.getResource(AspectJWeavingEnabler.ASPECTJ_AOP_XML_RESOURCE) != null);}}

判断是否启用AspectJ的逻辑是:

  1. 如果配置aspectj-weaving=on则表示开启
  2. 如果配置aspectj-weaving=off则表示不开启,关闭
  3. 其他情况,判断当前环境下是否存在META-INF/aop.xml,如果存在,表示开启AspectJ

如果确认需要开启AspectJ,则会向IOC容器中,注册org.springframework.context.weaving.AspectJWeavingEnabler

org.springframework.context.weaving.DefaultContextLoadTimeWeaver

这里DefaultContextLoadTimeWeaver是默认实现,如果在 \<context:load-time-weaver weaver-class="xxxx.xxx"/> 配置了weaver-class这里会注册该类

这两个对应名称为:
ASPECTJ_WEAVING_ENABLER_BEAN_NAME =
“org.springframework.context.config.internalAspectJWeavingEnabler” -> AspectJWeavingEnabler

上面这几步,完成了AspectJ的相关准备工作,但是并没有进行织入,前面我们在研究spring容器启动过程分析的时候,有一步是进行AspectJ的织入。
spring容器启动过程分析

在AbstactApplicationContext.invokeBeanFactoryPostProcessors时候,会加入LoadTimeWeaverAwareProcessor

 protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));}}

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

这里首先会判断当前处理bean是否是LoadTimeWeaverAware,整个spirng中只有前面提到的AspectJWeavingEnabler实现了该接口。
而此时this.loadTimeWeaver并没有实例化,直接通过getBean获取,此时获取的就是之前说过的DefaultContextLoadTimeWeaver(或者手动指定)
DefaultContextLoadTimeWeaver实现了BeanClassLoaderAware接口,在其setBeanClassLoader逻辑:

// DefaultContextLoadTimeWeaver.java
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");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");}}}

其中:

else if (InstrumentationLoadTimeWeaver.isInstrumentationAvailable()) {
logger.debug(“Found Spring’s JVM agent for instrumentation”);
this.loadTimeWeaver = new InstrumentationLoadTimeWeaver(classLoader);
}

经过上述处理后,

AspectJWeavingEnabler.loadTimeWeaver = DefaultContextLoadTimeWeaver

DefaultContextLoadTimeWeaver.loadTimeWeaver = InstrumentationLoadTimeWeaver

AspectJWeavingEnabler同时实现了BeanFactoryPostProcessor,其postProcessBeanFactory实现如下:

// AspectJWeavingEnabler.java
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {enableAspectJWeaving(this.loadTimeWeaver, this.beanClassLoader);}/*** Enable AspectJ weaving with the given {@link LoadTimeWeaver}.* @param weaverToUse the LoadTimeWeaver to apply to (or {@code null} for a default weaver)* @param beanClassLoader the class loader to create a default weaver for (if necessary)*/public static void enableAspectJWeaving(@Nullable LoadTimeWeaver weaverToUse, @Nullable ClassLoader beanClassLoader) {if (weaverToUse == null) {if (InstrumentationLoadTimeWeaver.isInstrumentationAvailable()) {weaverToUse = new InstrumentationLoadTimeWeaver(beanClassLoader);}else {throw new IllegalStateException("No LoadTimeWeaver available");}}weaverToUse.addTransformer(new AspectJClassBypassingClassFileTransformer(new ClassPreProcessorAgentAdapter()));}/*** ClassFileTransformer decorator that suppresses processing of AspectJ* classes in order to avoid potential LinkageErrors.* @see org.springframework.context.annotation.LoadTimeWeavingConfiguration*/private static class AspectJClassBypassingClassFileTransformer implements ClassFileTransformer {private final ClassFileTransformer delegate;public AspectJClassBypassingClassFileTransformer(ClassFileTransformer delegate) {this.delegate = delegate;}@Overridepublic 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);}}

spring中load-time-weaver静态aop处理,基于aspectJ的静态aop处理相关推荐

  1. 第十篇 Spring AOP中Load Time Weaver

    文章目录 前言 一.先聊Load Time 二.再说Weaver 三.回看Load Time Weaver 四.LTW初始化过程 1.激活 2. Weave过程 总结 前言 本文介绍Spring AO ...

  2. Spring-aop 基于Aspectj 表达式配置AOP

    基于Aspectj 表达式配置AOP(推荐使用) 基于配置文件 1.添加切面对象(aspect对象) 2.把切面对象交给spring 3.配置文件 <?xml version="1.0 ...

  3. 基础XML配置的AOP与基于注解实现的AOP详细对比

    aop思想通过动态代理,一定程度上实现了代码的解耦.我们可以将日志模块,权限校验,事物等模块,与核心的业务代码相隔离,让程序员在写代码的时候,能够更加专注于业务. 基于注解实现AOP步骤: ①将目标类 ...

  4. Spring中AOP注解实现

    文章目录 AOP的一些名词 AOP具体实现 AOP的一些名词 连接点:类中可以被增强的方法 切入点:类中实际被增强的方法 通知:实际增强方法的部分 切面:把通知应用到切入点的过程 其中通知常用的有前置 ...

  5. Spring 学习 day3 : AOP,Spring中JdbcTemplate的使用

    1.AOP 1.1 什么是AOP 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方 式和运行期动态代理实现程序功能的统一维护的一种技术. ...

  6. 基于@AspectJ配置Spring AOP之一--转

    原文地址:http://tech.it168.com/j/2007-08-30/200708302209432.shtml 概述 在低版本Spring中定义一个切面是比较麻烦的,需要实现特定的接口,并 ...

  7. Spring AOP技术(基于AspectJ)的Annotation开发

    Spring AOP技术(基于AspectJ)的Annotation开发 @(Spring)[aop, spring, xml, Spring, annotation, aspectJ] Spring ...

  8. Spring AOP技术(基于AspectJ)的XML开发

    Spring AOP技术(基于AspectJ)的XML开发 @(Spring)[aop, spring, xml, Spring, annotation, aspectJ] Spring AOP技术基 ...

  9. Spring中的IOC介绍

    Spring中的IOC介绍 IOC(控制反转) IOC介绍 IOC是什么 IOC能做什么 Spring容器管理对象 1.maven管理依赖 2.给定容器的配置文件 3.IOC容器管理对象 4.通过容器 ...

最新文章

  1. ios 边录音边放_关于Android和iOS系统OneNote支持边录音边记笔记的需求和建议
  2. php三个数字比较大小排序,php中常用的4种实现数字大小排序的冒泡选择等算法函数代码...
  3. nssl1446-小智的旅行【dp】
  4. LeetCode 1935. 可以输入的最大单词数
  5. 《飞秋下载》介绍过的求伯君,看看!
  6. 报错,Error starting ApplicationContext. To display the conditions report re-run your application with
  7. 聊一聊 “超 大 模 型”
  8. 【06年博文搬家】一个修改时间的批处理程序
  9. 操作系统—用信号量机制实现进程互斥、进程同步和前驱关系
  10. matlab车牌识别源代码资源,车牌识别系统MATLAB源代码完整
  11. Unity TalkingData接入
  12. weblogic 启动很慢_【转】解决weblogic启动慢和创建域慢的方法
  13. 5步完成编写Mysql的shell脚本
  14. ssh 修改超时时间
  15. IOS开发工具介绍之Xcode开发工具使用
  16. 2021-10-26 数据存储的基本原理
  17. Java小农养成记第五天
  18. 源码时代 UI干货分享 | 如何用AI制作出迪士尼电影里的毛绒文字效果!!
  19. 船舶与海洋工程案例研究 | 达索系统百世慧®
  20. CKEditor 简单图片上传插件开发和详细步骤

热门文章

  1. 站长说说之SEO中浅谈如何做好新闻类网站的优化
  2. Shell中#*/和%/*是什么意思?
  3. 正则表达式环视否定例子
  4. 如何配置magento免运费商品方法
  5. 如何将所有商品改成免运费?
  6. Excel 2010 SQL应用055 SQL中使用三角函数
  7. 利用GDAL(python)读取Landsat8数据
  8. 【报告分享】2020大众心理健康洞察报告-简单心理(附下载)
  9. Transformer课程 第46章 Transformer模型TAPAS架构
  10. 电脑系统32位和64位有哪些区别 32位和64位是什么意思