在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使用率。其实这在实际生产中很有用,与其拉一堆性能测试工具,不如动手做个简单的分析切面,使我们能很快得到一些性能指标。我指的是没有硬性的性能测试需求下。

首先我们编写一个被织入的受体类,也就是被拦截的对象。

  1. public class DemoBean {
  2. public void run1() {
  3. System.out.println("run1...");
  4. }
  5. public void run2() throws Exception {
  6. TimeUnit.SECONDS.sleep(2);
  7. System.out.println("run2...");
  8. }
  9. }

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

  1. @Aspect
  2. public class ProfileAspect {
  3. @Around("profileMethod()")
  4. public Object profile(ProceedingJoinPoint pjp) throws Throwable {
  5. StopWatch sw = new StopWatch(getClass().getName());
  6. try {
  7. sw.start(pjp.getSignature().getName());
  8. return pjp.proceed();
  9. } finally {
  10. sw.stop();
  11. System.err.println(sw.prettyPrint());
  12. }
  13. }
  14. @Pointcut("execution(public * org.codetree.core.spring.loadtimeweaver.*.*(..))")
  15. public void profileMethod() {
  16. System.out.println("profileMethod..");
  17. }
  18. }

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

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

spring的配置文件

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4.  
  5. xmlns:context="http://www.springframework.org/schema/context"
  6. xsi:schemaLocation="http://www.springframework.org/schema/beans
  7. http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  8. http://www.springframework.org/schema/context
  9. http://www.springframework.org/schema/context/spring-context-3.0.xsd">
  10.  
  11. <context:load-time-weaver aspectj-weaving="autodetect" />
  12.  
  13. <context:component-scan base-package="org.codetree.core.spring.loadtimeweaver"
  14. use-default-filters="false">
  15. <context:include-filter type="regex"
  16. expression="org.codetree.core.spring.loadtimeweaver.*" />
  17. <context:exclude-filter type="regex"
  18. expression="org.codetree.core.spring.loadtimeweaver.Main" />
  19. </context:component-scan>
  20.  
  21. </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方法中。

测试类

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

结果

  1. 输出结果如下:
  2.  
  3. run1...
  4.  
  5. StopWatch 'ProfilingAspect': running time (millis) = 0
  6.  
  7. -----------------------------------------
  8.  
  9. ms % Task name
  10.  
  11. -----------------------------------------
  12.  
  13. 0001  100%  run1

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

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

spring的配置文件

  1. <?xml version="1.0" encoding="GBK"?>
  2.  
  3. <beans xmlns="http://www.springframework.org/schema/beans"
  4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
  5. xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
  6. xsi:schemaLocation="
  7. http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
  8. http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
  9. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
  10. http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

  11.    <context:load-time-weaver weaver-class="com.shansun.multidemo.spring.ExtInstrumentationLoadTimeWeaver" aspectj-weaving="autodetect" />
  12. <context:component-scan base-package="com.shansun.multidemo"></context:component-scan>
  13. </beans>

Spring的LoadTimeWeaver(代码织入)的更多相关文章

  1. Spring的LoadTimeWeaver(代码织入)(转)

    https://www.cnblogs.com/wade-luffy/p/6073702.html 在Java 语言中,从织入切面的方式上来看,存在三种织入方式:编译期织入.类加载期织入和运行期织入. ...

  2. 30个类手写Spring核心原理之AOP代码织入(5)

    本文节选自<Spring 5核心原理> 前面我们已经完成了Spring IoC.DI.MVC三大核心模块的功能,并保证了功能可用.接下来要完成Spring的另一个核心模块-AOP,这也是最 ...

  3. .NET静态代码织入——肉夹馍(Rougamo)

    肉夹馍是什么 肉夹馍通过静态代码织入方式实现AOP的组件..NET常用的AOP有Castle DynamicProxy.AspectCore等,以上两种AOP组件都是通过运行时生成一个代理类执行AOP ...

  4. .NET静态代码织入——肉夹馍(Rougamo) 发布1.1.0

    肉夹馍(https://github.com/inversionhourglass/Rougamo)通过静态代码织入方式实现AOP的组件,其主要特点是在编译时完成AOP代码织入,相比动态代理可以减少应 ...

  5. .NET静态代码织入——肉夹馍(Rougamo) 发布1.2.0

    肉夹馍(https://github.com/inversionhourglass/Rougamo)通过静态代码织入方式实现AOP的组件,其主要特点是在编译时完成AOP代码织入,相比动态代理可以减少应 ...

  6. Spring基础系列--AOP织入逻辑跟踪

    原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/9619910.html 其实在之前的源码解读里面,关于织入的部分并没有说清楚,那些前置.后 ...

  7. AOP的核心:代理与织入

    分为两步: 1.动态生成代理类: 2.织入: 2.6 织入(Weaving) 织入是将增强添加到目标的具体连接点上的过程 . AOP 织入方式: 方式 实现 应用编译期织入 特殊的 Java 编译器. ...

  8. Java AOP (1) compile time weaving 【Java 切面编程 (1) 编译期织入】

    According to wikipedia  aspect-oriented programming (AOP) is a programming paradigm that aims to inc ...

  9. SpringAOP03 项目脚手架、自定义注解、织入切面、引介增强

    1 项目脚手架 利用 Maven 进行创建 1.1 利用IDEA创建一个Maven原型项目 技巧01:原型Maven项目是没有webapp文件夹和resources项目文件夹的,需要自己手动创建:创建 ...

随机推荐

  1. js注册读秒进度条

    转载自://http://blog.csdn.net/wugouzi/article/details/12621385 <head> <meta http-equiv="C ...

  2. springmvc多文件上传

    @RequestMapping(value = "/upload", method = RequestMethod.POST) public void upload(@Reques ...

  3. 【python】dict4ini和xmltodict模块用途

    dict4ini模块:可以读写配置文件 xmltodict模块:将xml和json互相转换  https://pypi.python.org/pypi/xmltodict

  4. bootstrap弹出提示窗口功能

    大家常用弹出提示成功或失败时候喜欢用alert,如果不用这个,写个弹窗又麻烦,bootstrap中就有个方法 alert("操作成功"); commonAlert("操作 ...

  5. linux vi 中按了ctrl+s后没法退出

    linux vi 中按了ctrl+s后无法退出 Linux 中使用vi编辑文件 不小心按了Ctrl + S (习惯了) 结果终端就跟死了一样, 解决办法: Ctrl+Q

  6. Qt中如何添加.qrc文件

    You need a resource file (.qrc) within which you embed the input text file. The input file can be an ...

  7. 聊聊Android的APK反编译

    上一篇<How To Use Proguard in Android APP>介绍了如何对Android进行混淆,现在来对它进行反编译看看,里面有些什么东西. APK文件,其实也是一个压缩 ...

  8. 关于s:iterator 和s:if 的结合使用

    <s:iterator value="list" status="st"> <div class="sidebar-nav" ...

  9. codevs 1488GangGang的烦恼

    题目链接:http://codevs.cn/problem/1488/ 写个高精度大数运算就行 #include<cstdio> #include<iostream> #inc ...

  10. 启动ip转法功能

    这种方法无需重启: [root@ha02 ~]# cat /proc/sys/net/ipv4/ip_forward [root@ha02 ~]# sysctl -w net.ipv4.ip_forw ...