您的位置:首页 > 编程语言 > Java开发

spring-aop(一)基础知识

2016-09-27 00:00 363 查看
通知:切面的工作称为通知,通知定义了切面是什么以及何时用

连接点:

连接点是一个应用执行过程中能够插入一个切面的点。

连接点可以是调用方法时、抛出异常时、甚至修改字段时、

切面代码可以利用这些点插入到应用的正规流程中

程序执行过程中能够应用通知的所有点

切点:

如果通知定义了“什么”和“何时用”。那么切点就定义了“何处”。切点会匹配通知所要织入的一个或者多个连接点。

通常使用明确的类或者方法来指定这些切点。

作用:定义通知被应用的位置(在哪些连接点)

切面:通知和切点的结合(何时,何处 完成工作)

引入:

织入:

spring 提供4中类型的AOP支持 :1.基于代理的经典SpringAOP;2.纯POJO切面;3.@AspectJ注解驱动的切面;4.注入式AspectJ切面(适用于Spring各版本 )

spirng在运行时通知对象:代理拦截方法,当需要用到时才给到被代理的bean;

Spring只支持方法级别的连接点:如果方法拦截不能满足需求可以用Aspect来补充Spring AOP功能

4.2通过切点来选择连接点:只有execution指示器是编写切点定义的主要指示器。其他事限制所匹配的切点。

指示器:arg() ; @args(); execution(); this(); target; @target; within(); @within(); @annotation;

编写切点:execution(* concert.Performance.perform(..)) && within(concert.*) --执行concert包下的Performacnce类中的perform方法,但限定只匹配concert包。&&还可以有 “||”;“!”

在切点中选择bean:使用bean的id或者bean的名称:execution(* concert.Performance.perform(..)) and bean('woodstock') --执行Performance的perform()方法是应用通知,但限定bean的ID为woodstock

4.3使用注解创建切面:

4.3.1:定义切面,观众对于一场演出来说不是最核心的,所以观众定义为演出的一个切面,应用于演出

@Aspect
public class Audience{
@Pointcut("execution(** concert.Performance.perform(..))")
public void performance(){

@Before("performance()")   //前置通知
public void silenceCellphones(){
Sysotem.out.println("Silencing cell phones");

}
@Before("performance()")    //前置通知
public void takeSeats(){
Sysotem.out.println("Takeing seats");
}
@AfterReturning("performance()")   //后置通知
public void applause(){
Sysotem.out.println("Clap Clap Clap!!!");
}
@AfterThrowing("performance()")  //通知方法会将目标方法封装起来。
public void demandRefund(){
Sysotem.out.println("Demanding a refund");
}
}
}

Audience 只是一个java类,只不过它公国注解表明会作为切面使用而已;

装配为Spring中的Bean:

@Bean
public Audience audience(){
return new Audience();
}

启动自动代理功能:

package concert

@Configuration
@EnableAspectJAutoProxy  //启用AspectJ自动代理
@ComponentScan
public class ConcertConfig{

@Bean
public Audience audience(){		//声明Audience bean
return new Audience();
}
}

也可以用xml来装配bean :<aop:aspectj-autoproxy>

这样AspectJ自动代理会为使用@Aspect注解的bean创建一个代理 “切面基于代理”

4.3.2 创建环绕通知

@Aspect
public class Audience{
@Pointcut("execution(** concert.Performance.perform(..))")    //定义命名的切点
public void performance(){}

@Around("performance()")
public void watchPerformance(ProceedingJonPoint jp){
try{
Sysotem.out.println("Silencing cell phones");
Sysotem.out.println("Takeing seats");
jp.proceed();
Sysotem.out.println("Clap Clap Clap!!!");
} catch(Throwable e){
Sysotem.out.println("Demanding a refund");
}

}

}

通知中通过ProceedingJonPoint 对象来调用被通知的方法

4.3.3 处理通知中的参数

@Aspect
public class TrackCounterImpl implements ITrackCounter {

private Map<Integer, Integer>trackCounts = new HashMap<Integer, Integer>();

@Pointcut("execution(* soundsystem.CompactDisc.playTrack(int))" + "&& args(trackNumber)")
//"&& args(trackNumber)")限定传递给playTTrack()的int类型参数也会传递到通知中
public void trackPlayed(int trackNumber){}

@Before("trackPlayed(trackNumber)")
public void countTrack(int trackNumber){
int currentCount = getPlayCount(trackNumber);
trackCounts.put(trackNumber,  currentCount + 1);
}

public int getPlayCount(int trackNumber){
return trackCounts.containsKey(trackNumber) ? trackCounts.get(trackNumber) : 0;
}

}

用 @Pointcut注解 命名切点 execution(* soundsystem.CompactDisc.playTrack(int)) && args(trackNumber) 并用@Before前置通知,args(trackNumber)完成了 从命名切点到通知方法的参数转移。

4.3.4 通过注解引入新功能
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  spring aop