AspectJ在Spring中的使用
在上一篇AspectJ的入门中,简单的介绍了下AspectJ的使用,主要是以AspectJ的example作为例子。介绍完后也留下了几个问题:
1)我们在spring中并没有看到需要aspectj之类的关键词,而是使用java代码就可以了,这是如何做到的
2)Spring中如何做到不使用特殊的编译器实现aop的(AspectJ如何在运行期使用)
3)Spring源码中与aspectJ 相关的AjType究竟是啥?
这篇文章会继续试着解决这几个问题。
aspectJ的几种织入方式
compile-time、post-compile 和 load-time Weavers
首先了解下AspectJ的几种织入方式,分别是compile-time、post-compile 和 load-time,分别对应着编译期、后编译期、加载期织入
编译期织入
首先是编译期织入,上一篇博客所介绍的方式就是使用的编译期织入。很容易理解,普通的java源码
+ aspectJ特殊语法的‘配置’ 文件 + aspectJ特殊的编译器
,编译时候生成已织入后的.class文件,运行时直接运行即可。
后编译期织入
后编译期织入和编译期的不同在于,织入的是class字节码或者jar文件。这种形式,可以织入一个已经织入过一次的切面。同样这种情况也需要特殊的编译器
加载期织入
加载期顾名思义,是在类被加载进虚拟机之前
织入,使用这种方式,须使用AspectJ agent。
了解了这些概念,下面就要知道,spring是使用哪种呢?spring哪一种都不是,spring是在运行期
进行的织入。
Spring 如何使用AspectJ
AspectJ 本身是不支持运行期织入的,日常使用时候,我们经常回听说,spring 使用了aspectJ实现了aop,听起来好像spring的aop完全是依赖于aspectJ
其实spring对于aop的实现是通过动态代理(jdk的动态代理或者cglib的动态代理),它只是使用了aspectJ的Annotation,并没有使用它的编译期和织入器,也就是说spring并不是直接使用aspectJ实现aop的
spring aop与aspectJ的区别
看了很多篇博客以及源码,我对spring aop与aspectJ的理解大概是这样;
1)spring aop 使用AspectJ语法的一个子集,一些method call, class member set/get 等aspectJ支持的语法它都不支持
2)spring aop 底层是动态代理,所以受限于这点,有些增强就做不到,比如 调用自己的方法就无法走代理
看下下面的例子:
@Component
public class A{
public void method1(){
method2();
}
public void method2(){
//...
}
}
这个时候method2是无法被切到
的,要想被切到可以通过如下奇葩的方式:
@Component
public class A{
@Autowired
private A a;
public void method1(){
a.method2();
}
public void method2(){
//...
}
}
之前碰到这样的问题时,我还特别不能理解,现在想下aop的底层实现方式就很容易理解了。
在之前写的jdk动态代理与cglib动态代理实现原理,我们知道了jdk动态代理是通过动态生成一个类的方式实现的代理,也就是说代理是不会修改底层类字节码的
,所以可能生成的代理方法是这样的
public void method1(){
//执行一段代码
a.method1()
//执行一段代码
}
public void method2(){
//执行一段代码
a.method2()
//执行一段代码
}
回头看a.method1()的源码,也就明白了,为啥method2()没有被切到,因为a.method1()执行的方法,最后调用的不是 代理对象.method2(),而是它自己的method2()(this.method2()) 这个方法本身没有任何改动
反观aspectJ,aspectJ是在编译期修改了方法(类本身的字节码被改了),所以可以很轻松地实现调用自己的方法时候的增强。
3)spring aop的代理必须依赖于bean被spring管理,所以如果项目没有使用spring,又想使用aop,那就只能使用aspectJ了(不过现在没有用spring的项目应该挺少的吧。。。)
4)aspectJ由于是编译期进行的织入,性能会比spring好一点
5)spring可以通过@EnableLoadTimeWeaving 开启加载期织入(只是知道这个东西,没怎么研究。。有兴趣的可以自己去研究下)
6)spring aop很多概念和aspectJ是一致的
AspectJ的注解在spring aop中的应用
了解了spring与aspectJ的关系后,就能更清晰的了解spring 的aop了。
先说明一点,虽然我介绍aspect的配置时,一直介绍的aspectJ文件配置方式,但是aspectJ本身是支持注解方式配置的。可以看官方文档,注解在aspectJ中的使用
而spring 使用了aspectJ注解的一小部分(正如前面所说的,受限于jdk的动态代理,spring只支持方法级别的切面)
回头看看AjType
回头看看之前看到的这段源码,什么是AjType,经过aspectJ解析器解析后对类的一种描述,比如正常的方法可能是这样
/*
* 配置前置通知,使用在方法aspect()上注册的切入点
* 同时接受JoinPoint切入点对象,可以没有该参数
*/
@Before("aspect()")
public void before(JoinPoint joinPoint) {
log.info("before " + joinPoint);
}
在AjType中就能获取到很多其他的aspectJ所需的相关信息(除了java反射所能获取到的信息以外)
/**
* Return the pointcut object representing the specified pointcut declared by this type
*/
public Pointcut getDeclaredPointcut(String name) throws NoSuchPointcutException;
/**
* Return the pointcut object representing the specified public pointcut
*/
public Pointcut getPointcut(String name) throws NoSuchPointcutException;
比如看着两个方法,可以获取到切入点信息。
在看看PerClauseKind.SINGLETON
这里就复用了aspectJ的概念
总结下
这篇文章回答了之前学习aspectJ时候碰到的几个问题,然后讨论了下aspectJ在spring中的应用。最大的收获是了解了spring与aspectJ 的关系,了解了两者对aop的不同实现所造成的使用上的影响。以后当遇到了spring aop相关的概念如果不理解,可以去aspectJ上去搜搜看了 = =
原文链接
本文为云栖社区原创内容,未经允许不得转载。
AspectJ在Spring中的使用的更多相关文章
- spring中AspectJ的使用
目录 AspectJ: AOP术语 通知的类型 切入点表达式 基于xml的AspectJ编程 导入jar包 定义切面类 引入约束 AOP配置 基于注解的AspectJ编程 AspectJ: 什么是AO ...
- 在Spring中使用AspectJ实现AOP
在Spring中,最常用的AOP框架是AspectJ,使用AspectJ实现AOP有2种方式: 基于XML的声明式AspectJ 基于注解的声明式AspectJ 基于XML的声明式AspectJ 1. ...
- Spring实战(十二) Spring中注入AspectJ切面
1.Spring AOP与AspectJ Spring AOP与AspectJ相比,是一个功能比较弱的AOP解决方案. AspectJ提供了许多它不能支持的类型切点,如在创建对象时应用通知,构造器切点 ...
- Spring 中基于 AOP 的 @AspectJ
Spring 中基于 AOP 的 @AspectJ @AspectJ 作为通过 Java 5 注释注释的普通的 Java 类,它指的是声明 aspects 的一种风格. 通过在你的基于架构的 XML ...
- Spring中文文档-第一部分
一. Spring 框架概述 Spring是为了构建企业应用的轻量级框架.然而,Spring是模块化的,允许你只是使用其中的一部分,不需要引入其他的.你可以在任何web框架上使用IoC容器,也可以只使 ...
- Spring中文文档
前一段时间翻译了Jetty的一部分文档,感觉对阅读英文没有大的提高(*^-^*),毕竟Jetty的受众面还是比较小的,而且翻译过程中发现Jetty的文档写的不是很好,所以呢翻译的兴趣慢慢就不大了,只能 ...
- 基于@AspectJ配置Spring AOP之一--转
原文地址:http://tech.it168.com/j/2007-08-30/200708302209432.shtml 概述 在低版本Spring中定义一个切面是比较麻烦的,需要实现特定的接口,并 ...
- Spring中的通知(Advice)和顾问(Advisor)
在Spring中,目前我学习了几种增强的方式,和大家分享一下 之前的话: 1.AOP (Aspect Oriented Programming 面向切面编程) 在软件业,AOP为Aspect O ...
- 浅析Spring中的注解
Spring的配置,通常有两种:使用配置文件和注解.那么Spring如何知道各个Bean或者Service.Controller以及Bean中各类属性之间的关系呢?答案肯定是在定义各个Java文件的时 ...
随机推荐
- 计算机爱好者协会技术贴markdown第四期
首先先让爱酱用CSDN自带的数学公式方法来闪瞎大家的钛合金狗眼: 有没有感觉到Markdown的强大!!!!! ## KaTeX数学公式 您可以使用渲染LaTeX数学表达式 [KaTeX](https ...
- JavaWeb三大组件之Servlet
http://tomcat.apache.org/tomcat-5.5-doc/servletapi/javax/servlet/Servlet.html 一.Servlet继承结构体系图 从结构图中 ...
- OpenGIS
OpenGIS(Open Geodata Interoperation Specification,OGIS-开放的地理数据互操作规范)由美国OGC(OpenGIS协会,Open Geospatial ...
- bzoj1031(sa)
省选前练习模板系列: #include<iostream> #include<cstdio> #include<cmath> #include<cstring ...
- ajax提交数组至后台,无法获取值得问题
$(".delAll_btn").click(function(){ var checkStatus = table.checkStatus('userList'), data = ...
- Eclipse下用NDK编译生成so文件
我们在安装环境的时候安装了NDK,可以在eclipse下直接生成so文件.NDK的压缩包里面自带了一些sample工程,NDK的文件直接解压到某个目录下即可. 第一次生成so文件的时候,我们先使用 ...
- JavaScript自定义鼠标右键菜单
下面为JavaScript代码 window.onload = function () { //好友列表 var f = 0; //判断指定id的元素在页面中是否存在 if (document.get ...
- listcard记录
.listcard-bg{ .listcard-head{ background: #F34A55; width: 100%; height: 50px; margin-bottom: -50px; ...
- Python之路【第三篇】编码
Python代码——>字节码——>机器码——>计算机 Windows: cmd ==> python 文件路径 cmd ==>python >> 输入命令 L ...
- 在windows上安装wamp时遇到apache无法启动,图标为橙色
1.首先测试端口号是否被占用,如果端口号被占用,修改相对应文件的端口号,修改端口号的方法网上很容易搜到. 2.如果端口号没有被占用,cd到httpd.exe目录下,查看错误原因,这里我显示的错误是ht ...