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

Spring学习03--AOP基础知识和常规用法

2020-03-01 20:40 302 查看

AOP常用术语

通知(Advice):切面的工作被称为通知。它定义了“何时”、“怎样”的概念。Spring切面可以应用5种类型的通知

  1. 前置通知(Before):在目标方法被调用之前调用通知功能。
  2. 后置通知(After):在目标方法完成之后调用通知,不关心方法的输出是什么
  3. 返回通知(After-returning):在目标方法成功执行之后调用通知
  4. 异常通知(After-throwing):在目标方法抛出异常后调用通知
  5. 环绕通知(Around):通知包裹了目标方法,在被调用之前和调用之后执行自定义的行为
    连接点(Join point):切面插入应用执行过程的时机,可以是调用发放时,可以是抛出异常时,
    甚至是修改一个字段时。
  6. 切点(Pointcut):通知织入的一个或多个连接点。
  7. 切面(Aspect):通知和切点的结合。在何时(Advice)何处(Joincut)完成怎样(Advice)的动作
  8. 引入(Introdction):在不修改现有类的情况下,向现有的类添加新方法或属性。
  9. 织入(Weaving):把切面应用到目标对象并创建新的代理对象的过程。切面在指定的连接点被织入到目标对象中。在目标对象的生命周期里有多个点可以进行织入:
    #编译期:切面在目标类编译时被织入。这种方式需要特殊的编译器。AspectJ的织入编译器就是以这种方式实现。
    #类加载期:切面在目标类加载到JVM时被织入。
    #运行期:切面在应用运行的每个时刻被织入。一般情况下,切面在织入时,AOP容器会为目标对象动态地创建一个代理对象。SpringAOP就是以这种方式织入
    Spring提供了4种类型的SpringAOP支持:
    1.基于经典的SpirngAOP
    2.纯POJO切面
    3.@AspectJ注解驱动的切面
    4.注入式AspectJ切面
    看完了上面AOP相关基础知识,接下来实际看一下代码中AOP的应用。假定一个场景,某舞团来我市进行一场表演
//表演可能是现代舞表演,可能是民族舞表演等等...
public interface Performance{
public void perform();
}

表演快开始了,观众进场。1.观众找到自己的位置就做;2.观众很有素质,把手机调成了静音。(不管是什么表演,观众就做和手机静音两项是不是都需要完成的,而跟什么表演无关),这是不是很符合AOP的使用场景,所以我们创建一个观众类Audience,并给它添加上就坐takeseats和给手机静音siliencePhones两个方法。

public class Audience{
public void takeSeats(){
System.out.println("Taking seats");
}
public void sliencePhone(){
System.out.println("Sliencing cellPhones");
}
}

Audience只是一个普通JOPO类,我们用注解的方式来实现这个切面

@Aspect
public class Audience{
@Before("execution(** Perforence.perform(..))")
public void takeSeats(){
System.out.println("Taking seats");
}
@Before("execution(** Perforence.perform(..))")
public void sliencePhone(){
System.out.println("Sliencing cellPhones");
}
}

如上,@Aspect表示该类作为切面使用,@Before声明为前置通知,execution(** Perforence.perform(…))为ES6的语法,声明切点。但到此为止Audience仍然只会是Spring容器中的一个bean,即便有了@Aspect注解,它也不睡被视为切面,为了创建将其转换为切面的代理,下面我们通过Java配置的方式来实现。

@Configuration
@EnableAspectJAutoProxy
@ComponentScan
public class PerformanceConfig{
@Bean
pulic Audience audience(){
return new Audience();
}
}

@EnableAspectJAutoProxy注解功能为启用自动代理,生成Audience的代理类,织入目标类Perfomance中,拦截被通知方法perform的调用,执行切面逻辑,再把调用转发给目标bean(Performance);同理,接下来我们把后置通知@After,异常通知@After-throwing,返回通知@After-returnning,加入进来

@Aspect
public class Audience{
@Before("execution(** Perforence.perform(..))")
public void takeSeats(){//表演前 就座
System.out.println("Taking seats");
}
@Before("execution(** Perforence.perform(..))")
public void sliencePhone(){//表演前  手机静音
System.out.println("Sliencing cellPhones");
}
@AfterReturnning("execution(** Perforence.perform(..))")
public void applause(){//表演结束  鼓掌
System.out.println("CLAP CLAP CLAP!!!");
}
@AfterThrowing("execution(** Perforence.perform(..))")
public void demandRefund(){//表演失败 退款
System.out.println("Demanding a refund");
}
}

仔细看上面的代码,发现execution(** Perforence.perform(…))被重复使用多次,可以优化一下,声明切点并通过引用来使用它

@Aspect
public class Audience{
//声明切点 通过引用调用
@Pointcut("execution(** Perforence.perform(..))")
public void performance(){}
@Before("performance()")
public void takeSeats(){//表演前 就座
System.out.println("Taking seats");
}
@Before("performance()")
public void sliencePhone(){//表演前  手机静音
System.out.println("Sliencing cellPhones");
}
@AfterReturnning("performance()")
public void applause(){//表演结束  鼓掌
System.out.println("CLAP CLAP CLAP!!!");
}
@AfterThrowing("performance()")
public void demandRefund(){//表演失败 退款
System.out.println("Demanding a refund");
}
}

一开始我们就说了又5种类型的通知,上面我们已经使用了4种类型的通知,还有最后一种还没有使用过——环绕通知@Around,与其他通知不同,环绕通知能够将被通知方法完全包裹起来。通过下面的例子我们来认识下环绕通知

@Aspect
public class Audience{
@Pointcut("execution(** Perforence.perform(..))")
public void performance(){}
@Around("perfomance()")
public void aroundPerform(ProceedingJoinPoint jp){
try{
System.out.println("Taking seats");//演出前-就坐
System.out.println("Sliencing cellPhones");//演出前-手机静音
jp.proceed();//调用被通知方法(perform)-演出中
System.out.println("CLAP CLAP CLAP!!!");//演出完成 -鼓掌
}catch(Throwable e){
System.out.println("Demanding a refund");//演出失败-退款
}
}

可以看到@Around完全将目标方法包裹,类似于在一个方法中同时编写了前置/后置通知。
到目前为止我们所有的切面都很简单,都是没有带参数的。因为perform()方法本身不带参。如果通知带参呢,切面能访问和传递被通知方法的参数吗?

  • 点赞
  • 收藏
  • 分享
  • 文章举报
hyf9457 发布了3 篇原创文章 · 获赞 0 · 访问量 172 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: