Spring MVC学习笔记(四)

第4章 面向切面的Spring
1,通知(Advice);切面的工作呗称为通知
前置通知(Before)
后置通知(After)
返回通知(After-returning)
异常通知(After-throwing)
环绕通知(Around)
2,连接点(Joint point):在应用执行过程中能够插入切面的一个点。这个点可以是调用方法时,抛出异常时,甚至修改一个字段时。切面代码可以利用这些点插入到应用的正常流程之中,并添加新的行为。
3,切点(PointCut):切点的定义会匹配通知所要织入的一个或多个连接点。通常使用明确的类和方法名称,或是利用正则表达式定义所匹配的类和方法名称来指定这些切点。
如果说通知定义了切面的“什么”和“何时”的话,那么切点就定义了“何处”。
4,切面(Aspect)切面是通知和切点的结合。
5,织入(Weaving):把切面应用到目标对象并创建新的代理对象的过程。
6,创建切点来定义切面所织入的连接点是AOP框架的基本功能。
Spring提供了4中类型的AOP支持:
基于代理的经典Spring AOP:构建在动态代理基础之上,因此,Spring对AOP的支持局限于方法拦截。过于复杂,没介绍。
纯POJO切面:借助Spring的AOP命名空间,需要XML配置
@AspectJ注解驱动的切面
注入式AspectJ切面:超过简单的方法调用(如构造器或属性拦截)时使用
7,Spring的切面由包裹了目标对象的代理类实现。代理类处理方法的调用,执行额外的切面逻辑,并调用目标方法。
直到应用需要被代理的bean时,Spring才创建代理对象。如果使用的是ApplicationContext的话,在ApplicationContext从BeanFactory中加载所有bean的时候,Spring才会创建被代理的对象。
8,Spring用到的AspectJ切点表达式
execution:实际执行匹配,用于匹配是连接点的执行方法
execution(* concert.Performance.perform(..)) //返回任意类型 方法所属的类  方法 使用任意参数
execution(* concert.Performance.perform(..)) && within(concert.*) !bean('woodstock')  //当concert包下得任意类的方法被调用时,使用within()指示器限制切点范围;  切面的通知会被编制到所有ID不为woodstock的bean中
9,@Aspect 表明该类不仅是一个POJO,还是一个切面。  @Pointcut注解能够在一个@AspectJ切面内定义可重用的切点。
@Aspect
public class Audience{

@Pointcut("execution(** concert.Performance.perform(..))")//定义命名的切点,为@PointCut注解设置的值是一个切点表达式,通过在performance方法上添加@PointCut注解,我们实际上扩展了切点表达式语言,这样就可以在任何的切点表达中使用Performance()了。
public void performance(){}//Performance()方法的实际内容并不重要,在这里它实际上应该是空的。其实该方法本身只是一个标识,供@PointCut注解依附

@Before("performance()")
public void silenceCellPhone() {
System.out.println("Silencing cell phones");
}
即使使用了AspectJ注解,但Audience并不会被视为切面,这些注解不会解析,也不会创建将其转换为切面的代理。需要做如下操作:
@Configuration
@EnableAspectJAutoProxy  //启用AspectJ自动代理
@ComponentScan
public class ConcertConfig {

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

或者xml配置:


10,环绕通知(Around)
@Aspect
public class Audience{
@Pointcut("execution(** concert.Performance.perform(..))")
public void performance(){}

@Around("performance()")
public void watchPerfomance(ProceedingJoinPoint jp) {
...
jp.proceed();
...
}
11,处理通知中的参数
@PointCut{
"execution(* soundsystem.CompactDisc.playTrack(int)) && args(trackNumber)") //返回任意类型 方法所属的类  方法 接受int类型的参数  指定参数,表明传递给playTrack()方法的int类型参数也会传递到通知中去。
public void trackPlayed(int trackNumber) {}

@Before("trackPlayed(trackNumber)")
public void countTrack(int trackNumber) {
int currentCount = getPlayCount(trackNumber);
trackCounts.put(trackNumber,currentCount + 1);
}
12,属性拦截
@Aspect
public class EncoreableIntroducer{
@DeclareParents(value="concert.Performance+",//通过@DeclareParents注解,将Ecoreable接口引入到Performance bean中 value属性指定哪种类型的bean要引入该接口,标记符后面的加号表示是Performance的所有子类型,而不是Performance本身
                defaultImpl=DefaultEncoreable.class)//defaultImpl指定了为引入功能提供实现的类
public static Encoreable encoreable;//@DeclareParents注解所标注的静态属性指明了要引入了接口
和其他的切面一样,我们需要在Spring应用中将EncoreableIntroducer声明为一个bean:

面向注解的切面声明有一个明显的劣势:必须能够为通知栏添加注解。为了做到这一点,必须要有源码。
13,XML配置

     //引用audience Bean
            pointcut="execution(* concert.Performance.perform(..)) "
        method="silenceCellPhone"/>
        ....
              type-matching="concert.Performance+"
         implements-interface="concert.Encoreable"
         delegate-ref="encoreableDelegate"
         />
    



pointcut-ref 

你可能感兴趣的:(学习记录,Spring)