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

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()方法本身不带参。如果通知带参呢,切面能访问和传递被通知方法的参数吗?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值