3.AOP
2019-04-23 本文已影响0人
9156523
面向切面的Spring
在一般的程序开发中,在每一个功能模块中都有相同的操作,例如打印日志,事务操作等一系列重复动作,而Spring AOP指的就是把这种重复工作横向抽取出来,让程序员只需要关注业务
下面是关于AOP的相关术语
通知
:简而言之就是被抽取出来的方法
连接点
:可以插入通知的点
切点
:需要被插入通知的点
切面
:切点和通知构成了一个切面
织入
:把切面应用到目标对象并创建新的代理对象过程
使用注解的方式定义切面
可以在类前使用@Aspect
,代表这个是个切面类,一下代表的是在perform方法调用之前执行这个方法
@Aspect
public class Audience{
@Before("execution (** concert.Performace.perform(..))")
public void silenceCellPhones(){
System.out.prinln("Silencing cell phones");
}
}
如果相同的切点被频繁的使用,可以使用@pointcut,被定义为@Pointcut的实际方法内容不重要,他只是作为一个标识
public class Audience{
@Pointcut("execution (** concert.Performance.perform(..))")
public void performance(){}
@Before("performance()")
public void silenceCellPhones(){
System.out.println("aa");
}
}
定义了切面类以后,需要使用配置来自动装配被@Aspect修饰的类
使用JavaConfig启动自动代理
@Configuration
@EnableAspectJAutoProxy
@ComponentScan
public class ConcertConfig{
@Bean
public Audience audience(){
return new Audience();
}
}
使用xml
<context:component-scan base-package="concert" />
<aop:aspectj-autoproxy /> 启动AspectJ自动代理
在xml中声明切面
在前面所说的切面定义中,使用java配置优于xml配置,但是java配置的缺点就是必须要有源码,所以,了解在xml中声明切面是必须的
<aop:config>
<aop:aspect ref="Bean"> <!--引用一个切面类-->
<!--before 前置通知-->
<!--pointcut切入点,代表需要被插入通知的方法的地方-->
<!--method 通知,代表插入的方法 -->
<aop:before
pointcut="execution(** 包名.类名.方法名(..))"
method="insertMethod" //通知
/>
同理 before改成after-returning代表后置通知,且方法被执行完成以后才会执行
after代表无论方法是否执行成功都会执行
after-thorwing代表抛出异常以后会执行的方法
</aop:config>
如果多个通知都是在同一个切点,这样就要重复写很多同样的pointcut,我们可以为切点命名,如下,这样我们就可以使用pointcut-ref直接指定id号获取切点,如果想要这个切点可以被所有切面所引用,可以把这个节点放在config下
<aop:config>
<aop:aspect ref="audience">
<aop:pointcut id="idName" expression="execution ..."
</aop:aspect>
</aop:config>
环绕通知
环绕通知指的是 既可以执行前置通知 然后在执行被通知方法,最后在执行后置通知,环绕通知的好处是因为环绕通知是一个方法,所以变量是共享的,如果使用前置和后置通知,你在前置通知中定义的变量肯定是不能被后置通知访问的
环绕通知必须有参数,因为需要调用被通知函数
public void roundMethod(ProceedingJoinPoint jp){
try{
//前置方法
System.out.println("前置方法")
jp.proceed();//调用被通知方法
System.out.println("后置方法")
}catch(Exception e){
System.out.println("异常之后的方法");
}
}
<aop:config>
<aop:aspect ref="aspectBean">
<aop:pointcut id="idName"
expression ="execution(** 包名.类名.方法(..))"
method ="roundMethod"
</aop:aspect>
<aop:config>
通过以上就可以达到前置、后置、异常的通知 织入到切点中