使用面向切面编程时,仍然在一个地方定义通用的功能,但是可以通过声明或注解的方式定义这个功能以何种方式在何处应用,而无需修改受影响的类。
散布于应用中多处的功能被称为横切关注点。这些横切关注点从概念上是与应用的业务逻辑相分离的(但往往会直接嵌入到应用的业务逻辑中)。横切关注点可以被模块化为特殊的类,这个类被称为切面。
依赖注入(DI)有助于应用对象之间的解耦;而AOP可以实现横切关注点与它们所影响的对象之间的解耦。
AOP术语 1、通知(Advice) 切面的工作(功能)被称为通知。通知定义了切面是什么以及何时使用。 Spring切面定义了五种类型的通知:
2、连接点(Join Point) 连接点是在应用执行过程中能够插入切面的一个点。这个点可以是调用方法时、抛出异常时、甚至修改一个字段时。切面代码可以利用这些点插入到应用的正常流程中,被添加新的行为。
3、切点(Poincut) 通知定义了切面是什么和何处,而切点定义了何处。一个切面并不需要通知应用的所有连接点。切点有助于缩小切面所通知的连接点的范围。切点的定义会匹配通知所要织入的一个或多个连接点。
4、切面(Aspect) 切面是通知和切点的结合。通知和切点共同定义了切面的全部内容:它是什么,在何时和何处完成其功能。
5、引入 引入允许我们向现有的类添加新方法或属性。从而可以在无需修改这些现有的类的情况下,让他们具有新的行为和状态。
6、织入 织入是把切面应用到目标对象并创建新的代理对象的过程。切面在指定的连接点被织入到目标对象中。在目标对象的生命周期里有多个点可以进行织入: 6.1、编译器:切面在目标类编译时被织入。 6.2、类加载期:切面在目标类加载到JVM时被织入。 6.3、运行期:切面在应用运行的某个时刻被织入。一般情况下,在织入切面时,AOP容器会为目标对象动态创建一个代理对象。Sping AOP就是以这种方式织入切面的。
因为Spring基于动态代理,所以Spring只支持方法连接点。
在Spring AOP中,要使用AspectJ的切点表达式语言来定义切点。Spring仅支持AspectJ切点指示器的一个子集:
Spring还引入了一个新的bean()指示器,它允许在切点表达式中使用bean的ID来标识bean。限制切点只匹配特定的Bean。
AspectJ类型匹配的通配符: *:匹配任意字符,但它只能匹配上下文中的一个元素 .. : 匹配任意字符,可以匹配上下文中的多个元素。如果在类型模式中,必须和*联合使用,匹配任何数量的子包;而在方法参数模式中匹配任何数量参数 + :匹配指定类型的子类型;仅能作为后缀放在类型模式后边
例如:
java.lang.Number+ :匹配java.lang包下的任何Number的子类型。比如java.lang.Integer,java.lang.BigInteger java..* :匹配java包及任何子包下的任何类型方法匹配表达式
注解? 修饰符? 返回值类型 类型声明?方法名(参数列表) 异常列表?注解:可选,方法上持有的注解; 修饰符:可选,比如 public; 返回值类型:必填,可以是任何类型模式;* 表示任何类型 类型声明:可选,可以是任何类型模式 方法名:必填,可以使用 * 进行模式匹配 参数列表:“()”表示方法没有任何参数;“(..)”表示匹配接受任意个参数的方法,“(..,java.lang.String)”表示匹配接受java.lang.String类型的参数结束,且其前边可以接受有任意个参数的方法;“(java.lang.String,..)” 表示匹配接受java.lang.String类型的参数开始,且其后边可以接受任意个参数的方法;“(*,java.lang.String)” 表示匹配接受java.lang.String类型的参数结束,且其前边接受有一个任意类型参数的方法;
异常列表:可选,以“throws 异常全限定名列表”声明,异常全限定名列表如有多个以“,”分割,如throws java.lang.IllegalArgumentException, java.lang.ArrayIndexOutOfBoundsException。
组合切入点符号 AspectJ使用 且(&&)、或(||)、非(!)来组合切入点表达式。 可以使用and;or;not 来代替
切点使用例子: 1、execution:使用“execution(方法表达式)”匹配方法执行;
类型匹配表达式
注解? 类的全限定名字注解:可选,类型上持有的注解,如@Deprecated; 类的全限定名:必填,可以是任何类全限定名。
2、within:使用“within(类型表达式)”匹配指定类型内的方法执行
3、@within:使用“@within(注解类型)”匹配所有持有指定注解类型内的方法;注解类型也必须是全限定类型名
4、this:使用“this(类型全限定名)”匹配当前AOP代理对象类型的执行方法;注意是AOP代理对象的类型匹配,这样就可能包括引入接口方法也可以匹配;注意this中使用的表达式必须是类型全限定名,不支持通配符;
5、target:使用“target(类型全限定名)”匹配当前目标对象类型的执行方法;注意是目标对象的类型匹配,这样就不包括引入接口也类型匹配;注意target中使用的表达式必须是类型全限定名,不支持通配符;
6、@target:使用“@target(注解类型)”匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解;注解类型也必须是全限定类型名;
7、args:使用“args(参数类型列表)”匹配当前执行的方法传入的参数为指定类型的执行方法;注意是匹配传入的参数类型,不是匹配方法签名的参数类型;参数类型列表中的参数必须是类型全限定名,通配符不支持;args属于动态切入点,这种切入点开销非常大,非特殊情况最好不要使用;
8、@args:使用“@args(注解列表)”匹配当前执行的方法传入的参数持有指定注解的执行;注解类型也必须是全限定类型名;
9、@annotation:使用“@annotation(注解类型)”匹配当前执行方法持有指定注解的方法;注解类型也必须是全限定类型名;
10、bean:使用“bean(Bean id或名字通配符)”匹配特定名称的Bean对象的执行方法;Spring ASP扩展的,在AspectJ中无相应概念;
参考文章: http://jinnianshilongnian.iteye.com/blog/1415606