上一篇文章介绍了AOP的基本原理,即动态代理,Spring自身帮我们完成了动态代理的具体内容,我们只需要自行配置好相关就
可以实现基于切面的编程。
查阅Spring的参考文档,可以看到Spring定义了几个概念:
Aspect:切面,横切与多个类上的一个模块。在Spring的AOP实现中,这些切面都是由普通的class实现,可以通过Xml文件配置或者
通过@Aspect的注解类标注。
Join point:连接点,如果把多个方法的执行看做一条一条的线,切面看作横切与这些线的一个面,那个连接点就是线和面的交接。通
常来说,连接点就是被切面拦截的方法或者异常。通过Joint point可以获得被拦截的方法。
Advice:意见,在特定连接点处的切面采取的action,描述了这个切面要完成的工作以及何时完成。
Pointcut:切入点,定义了要被切面拦截的方法或类的名称,个人认为可以看做是Join point的集合。
AOP Proxy:代理,AOP框架产生的对象都是由JDK动态代理生成或CGLIB二进制生成的代理对象
Target:对象,即被织入的方法对象。
Weaving:织入,把切面应用到目标对象来创建新的代理对象的过程。
...
一般来说,为了方便开发,会引入AspectJ。其中又分Annotation和Xml两种配置方式。
1、Annotation配置
首先在xml配置文件中加入新的和aop相关的命名空间,并配置好schemalocation。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
之后再加入:
<aop:aspectj-autoproxy />
使其自动生成代理对象。这一过程是通过AspectJ来实现的,它是专门用来生成代理的工具。
之后就要定义切面。
package cn.wqy.aop;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class Interceptor {
@Before("execution(public void cn.wqy.biz.UserServiceImpl.addUser(cn.wqy.model.User))")
public void before(){
System.out.println("before");
}
}
其中用到了@Aspect来定义切面的具体类,并定义了@Before切面方法,其中要传递一个织入语句,相当于是pointcut,指定哪些类
被切面切。
方法还有:
织入语语法:
Ps:这里不光光要标注@Aspect,也要标注@Component,如不加@Component,则需要在Xml文件中配置一个该类对象的Bean。
2、XML方式配置
虽然Annotation的方式操作起来很方便,但是如果需要横切的方法很多,即需要处理很多的方法的话,Annotation就显得过于繁琐,
XML的配置方法则在这种情况时显现出了优势。
首先,加入aop等xml类库和schemalocation之后,加入对切面类的bean设置:
<bean id="TestInterceptor" class="cn.wqy.aop.Interceptor" />
之后,对aop具体进行配置:
<bean id="TestInterceptor" class="cn.wqy.aop.Interceptor" />
<aop:config>
<aop:pointcut
expression="execution(public void cn.wqy.biz.UserServiceImpl.addUser(cn.wqy.model.User))"
id="Test" />
<aop:aspect ref="TestInterceptor">
<aop:before method="before" pointcut-ref="Test" />
</aop:aspect>
</aop:config>
在<aop:config>标签下,首先配置了一个全局切入点,expression属性定义了被横切的类对象,id用来被引用。之后定义了一个切面
ref属性定义了切面中实现的方法。随后用子标签定义了执行何种方法,何时执行。
【“切面”参考“切面类对象”,“切面方法”参考“切入点”】
pointcut切入点同样可以定义在切面aspect内,则只是局部的切入点。
方法中的pointcut-ref可以不定义,则此时需要定义pointcut=“织入语法”直接指定切入点。