Spring的LoadTimeWeaver(代码织入)(转)
https://www.cnblogs.com/wade-luffy/p/6073702.html
在Java 语言中,从织入切面的方式上来看,存在三种织入方式:编译期织入、类加载期织入和运行期织入。编译期织入是指在Java编译期,采用特殊的编译器,将切面织入到Java类中;而类加载期织入则指通过特殊的类加载器,在类字节码加载到JVM时,织入切面;运行期织入则是采用CGLib工具或JDK动态代理进行切面的织入。
AspectJ采用编译期织入和类加载期织入的方式织入切面,是语言级的AOP实现,提供了完备的AOP支持。它用AspectJ语言定义切面,在编译期或类加载期将切面织入到Java类中。
AspectJ提供了两种切面织入方式,第一种通过特殊编译器,在编译期,将AspectJ语言编写的切面类织入到Java类中,可以通过一个Ant或Maven任务来完成这个操作;第二种方式是类加载期织入,也简称为LTW(Load Time Weaving)。 (只讲解第二种)
如何使用Load Time Weaving?首先,需要通过JVM的-javaagent参数设置LTW的织入器类包,以代理JVM默认的类加载器;第二,LTW织入器需要一个 aop.xml文件,在该文件中指定切面类和需要进行切面织入的目标类。

下面将通过一个简单的例子在描述如何使用LTW:
例子所作的是记录被调用方法的执行时间和CPU使用率。其实这在实际生产中很有用,与其拉一堆性能测试工具,不如动手做个简单的分析切面,使我们能很快得到一些性能指标。我指的是没有硬性的性能测试需求下。
首先我们编写一个被织入的受体类,也就是被拦截的对象。

public class DemoBean {
public void run1() {
System.out.println("run1...");
}
public void run2() throws Exception {
TimeUnit.SECONDS.sleep(2);
System.out.println("run2...");
}
}

接着,我们编写分析方法执行效率的切面。

@Aspect
public class ProfileAspect {
@Around("profileMethod()")
public Object profile(ProceedingJoinPoint pjp) throws Throwable {
StopWatch sw = new StopWatch(getClass().getName());
try {
sw.start(pjp.getSignature().getName());
return pjp.proceed();
} finally {
sw.stop();
System.err.println(sw.prettyPrint());
}
}
@Pointcut("execution(public * org.codetree.core.spring.loadtimeweaver.*.*(..))")
public void profileMethod() {
System.out.println("profileMethod..");
}
}

aop.xml。这个文件要求放在META-INF/aop.xml路径下,以告知AspectJ Weaver我们需要把ProfilingAspect织入到应用的哪些类中。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
<weaver>
<!-- only weave classes in your application-specific packages -->
<include within="org.codetree.core.spring.loadtimeweaver.*" />
</weaver>
<aspects>
<!-- weave in just these aspects -->
<aspect name="org.codetree.core.spring.loadtimeweaver.ProfileAspect" />
</aspects>
</aspectj>

spring的配置文件

<?xml version="1.0" encoding="utf-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <context:load-time-weaver aspectj-weaving="autodetect" /> <context:component-scan base-package="org.codetree.core.spring.loadtimeweaver"
use-default-filters="false">
<context:include-filter type="regex"
expression="org.codetree.core.spring.loadtimeweaver.*" />
<context:exclude-filter type="regex"
expression="org.codetree.core.spring.loadtimeweaver.Main" />
</context:component-scan> </beans>

或者
@EnableLoadTimeWeaving(aspectjWeaving=AspectJWeaving.AUTODETECT)
@EnableAspectJAutoProxy
@ComponentScan
通过 <context:load-time-weaver aspectj-weaving="on" /> 使 spring开启 loadtimeweaver, 注意 aspectj-weaving 有三个选项 : on, off, auto-detect, 如果设置为 auto-detect, spring 将会在 classpath 中查找aspejct 需要的 META-INF/aop.xml, 如果找到则开启 aspectj weaving,这个逻辑在LoadTimeWeaverBeanDefinitionParser#isAspectJWeavingEnabled方法中。
测试类

public class Main {
public static void main(String[] args) throws Exception {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:/spring/loadtimeweaver/loadtimeweaver.xml");
DemoBean demoBean = context.getBean(DemoBean.class);
demoBean.run1();
demoBean.run2();
}
}

结果

输出结果如下: run1... StopWatch 'ProfilingAspect': running time (millis) = 0 ----------------------------------------- ms % Task name ----------------------------------------- 0001 100% run1

如果想不加JVM的-javaagent参数可以进行如下替换:

public class ExtInstrumentationLoadTimeWeaver extends InstrumentationLoadTimeWeaver(默认的weaver) {
@Override
public void addTransformer(ClassFileTransformer transformer) {
try {
super.addTransformer(transformer);
} catch (Exception e) {吃掉无关异常不抛出}
}
}

spring的配置文件

<?xml version="1.0" encoding="GBK"?> <beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<context:load-time-weaver weaver-class="com.shansun.multidemo.spring.ExtInstrumentationLoadTimeWeaver" aspectj-weaving="autodetect" />
<context:component-scan base-package="com.shansun.multidemo"></context:component-scan>
</beans>

作者在写AOP对class的所有方法做拦截trace的时候发现嵌套调用的方法无法被拦截,因为在被拦截实体中再调用实体里的其他方法的时候,不是指向代理对象,而是当前对象, 于是找资料,在三种织入方式:编译期织入、类加载期织入和运行期织入,而spring里不管是用动态代理还是cglib都是运行期织入,关于这点美团的trace就是用加载器织入实现
Spring的LoadTimeWeaver(代码织入)(转)的更多相关文章
- Spring的LoadTimeWeaver(代码织入)
在Java 语言中,从织入切面的方式上来看,存在三种织入方式:编译期织入.类加载期织入和运行期织入.编译期织入是指在Java编译期,采用特殊的编译器,将切面织入到Java类中:而类加载期织入则指通过特 ...
- 30个类手写Spring核心原理之AOP代码织入(5)
本文节选自<Spring 5核心原理> 前面我们已经完成了Spring IoC.DI.MVC三大核心模块的功能,并保证了功能可用.接下来要完成Spring的另一个核心模块-AOP,这也是最 ...
- .NET静态代码织入——肉夹馍(Rougamo)
肉夹馍是什么 肉夹馍通过静态代码织入方式实现AOP的组件..NET常用的AOP有Castle DynamicProxy.AspectCore等,以上两种AOP组件都是通过运行时生成一个代理类执行AOP ...
- .NET静态代码织入——肉夹馍(Rougamo) 发布1.1.0
肉夹馍(https://github.com/inversionhourglass/Rougamo)通过静态代码织入方式实现AOP的组件,其主要特点是在编译时完成AOP代码织入,相比动态代理可以减少应 ...
- .NET静态代码织入——肉夹馍(Rougamo) 发布1.2.0
肉夹馍(https://github.com/inversionhourglass/Rougamo)通过静态代码织入方式实现AOP的组件,其主要特点是在编译时完成AOP代码织入,相比动态代理可以减少应 ...
- Spring基础系列--AOP织入逻辑跟踪
原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/9619910.html 其实在之前的源码解读里面,关于织入的部分并没有说清楚,那些前置.后 ...
- AOP的核心:代理与织入
分为两步: 1.动态生成代理类: 2.织入: 2.6 织入(Weaving) 织入是将增强添加到目标的具体连接点上的过程 . AOP 织入方式: 方式 实现 应用编译期织入 特殊的 Java 编译器. ...
- Java AOP (1) compile time weaving 【Java 切面编程 (1) 编译期织入】
According to wikipedia aspect-oriented programming (AOP) is a programming paradigm that aims to inc ...
- SpringAOP03 项目脚手架、自定义注解、织入切面、引介增强
1 项目脚手架 利用 Maven 进行创建 1.1 利用IDEA创建一个Maven原型项目 技巧01:原型Maven项目是没有webapp文件夹和resources项目文件夹的,需要自己手动创建:创建 ...
随机推荐
- 03 事务,连接池DBCP,C3P0,DBUtils
事务 Transaction 其实指的一组操作,里面包含许多个单一的逻辑.只要有一个逻辑没有执行成功,那么都算失败. 所有的数据都回归到最初的状态(回滚) 事务的作用:为了确保逻辑的成功. 例子: ...
- dp 优化 F2. Pictures with Kittens (hard version)
dp的优化可能是自己的弱项吧 F1中n*n*n的复杂度强行过去了 F2就无能为力了: 状态转移 dp[ i ] [ j ] 第一个i存的是位置 1-n; j是放入数字的个数 然后F1就暴力过去了 ...
- STM32F4的sct文件理解
原文地址http://blog.sina.com.cn/s/blog_898f36590100ya2l.html ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ...
- hdu2328 Corporate Identity 扩展KMP
Beside other services, ACM helps companies to clearly state their “corporate identity”, which includ ...
- 进入网站自动加自己为QQ好友代码
<meta http-equiv="refresh" content="0; url=tencent://AddContact/?fromId=50&fro ...
- AangularJS入门总结一
CRUD(增加Create.查询Retrieve.更新Update.删除Delete) 一.angularjs是为了克服HTML在构建应用上的不足而设计的: 二.AngularJS的出众之处: 构建一 ...
- 【BZOJ3514】 Codechef MARCH14 GERALD07加强版
hentai... 原题: N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数. 对于100%的数据,1≤N.M.K≤200,000. 直接复制wulala的题解 wulal ...
- Spring定时器corn表达式详解
1.结构 Spring定时器corn表达式详解 2.各字段的含义 字段 允许值 允许的特殊字符 秒 0~59 - * / 分 0~59 - * / 小时 0~23 - * / 日期 1~31 - * ...
- FastAdmin Git 开发更新流程
更加简洁的流程 FastAdmin 使用 Git 更新的新用法 https://www.cnblogs.com/F4NNIU/p/9120365.html
- day 29 socketsetserver 模块
1.FTP上传/下载服务端/客户端. --------------------------------------------------------------------------------- ...