Spring学习之旅(四):面向切面编程(AOP)

本文详细介绍了Spring框架中面向切面编程(AOP)的核心概念,包括通知、连接点、切点、切面、引入和织入等。阐述了不同类型的通知如前置、后置、返回、异常和环绕通知的应用场景,并通过实例演示如何在Spring中创建切点和切面。

Spring框架的核心是依赖注入和面向切面编程
面向切面(AOP)的术语是理解AOP的重要内容:
一.通知(Advice):通知定义了切面是什么,定义了切面的功能代码以及什么时候使用。
Spring切面可以应用五种类型的通知:
1.前置通知(Before):在目标方法被调用之前调用通知功能。
2.后置通知(After):在目标方法被调用之后调用通知功能。
3.返回通知(After-returning):在目标方法成功执行之后才调用通知功能。
4.异常通知(After-throwing):在目标方法抛出异常之后才调用通知功能。
5.环绕通知(Round):通知包裹了被通知方法,在被通知方法调用前后执行自定义行为。
二.连接点:连接点是在应用执行过程中可以插入切面的一个点,这个点可以是调用方法时,抛出异常时,甚至是修改一个字段时。
三.切点:切点定义了在何处,切点的定义会匹配通知所要织入的一个或多个连接点。
四.切面:切面是通知和切点的结合,定义了在何时何处做什么。
五.引入:引入允许我们在现有的类中添加新方法或者属性。
六.织入:织入是把切面应用到目标对象并创建新代理对象的过程。切面在指定的连接点被织入到目标对象当中。
有三个时机可以进行织入:
1.编译期:切面在目标类被编译时织入,需要特殊的编译器。AspectJ的织入编译器就是以这种方式织入得。
2.类加载期:切面在目标类加载到JVM时织入。
3.运行期:切面在应用运行时的某个时刻被织入,AOP容器会为目标对象动态地创建一个代理对象。Spring AOP就是这种方式。


Spring AOP构建于动态代理基础上,因此Spring AOP仅局限于方法拦截上。
如果你的AOP需求超过了简单的方法调用,那么你需要考虑使用AspectJ来实现切面。


编写切点:
我们使用接口Performance:

package com;
public interface Performance
{
    public void perform();
}
创建切点:
execution(* com.Performance.perform(..))

execution:关键字,用于在方法执行时触发。
*:表示接受任意的返回类型。
com.Performance.perform(..):方法的全限定名,..表示接受任何参数。

可以使用指示器来限制匹配:
指示器有:
1.args(类型):限制连接点匹配参数为指定类型的执行方法。
2.@arg():限制连接点匹配参数由指定注解标注的执行方法。
3.this():限制连接点匹配AOP代理的Bean引用为指定类型的类。
4.within():限制连接点指定的类型。
5.bean(bean id):限制切点只匹配特定的bean。
用and(&&),or(||),not(!)连接。


创建切面:

package com;
import org.aspectj.lang.annotation.*;
@Aspect      //表明该Bean是一个切面
public class Audience
{
    @Pointcut("execution(** com.Performance.perform(..))")
    public void performance(){}       //声明切点,可重用。
    @Before("performance()")
    //通知方法代码,在切点方法执行之前调用。
    @After("performance()")
    //通知方法代码,在切点方法执行后调用,不论执行方法是否成功执行。
    @AfterReturning("performance()")
    //通知方法代码,在切点方法成功执行,返回之后,才调用。
    @AfterThrowing("performance()")
    //通知代码,在切点方法抛出异常时调用。
}

需要为切面创建Bean。


需要将切面启用自动代理功能,才能成为真正的切面:

package com;
import org.springframework.context.annotation.*;
@Configuration
@EnableAspectJAutoProxy  //为切面启用自动代理
@ComponentScan   //自动扫描组件,会扫描@Aspect注解的类
public class MyConfig
{
    @Bean
    public Audience audience()
    {
        return new Audience();
    }
}

创建环绕通知:环绕通知是最强大的通知

package com;
import org.aspectj.lang.annotation.*;
@Aspect
public class Audience
{
    @Pointcut("execution(** com.Performance.perform(..))")
    public void performance(){}       //声明切点,可重用。
    @Around("performance()")
    public void aroundWatch(ProceedingJoinPoint jp)
    {
        try
        {
            //一些逻辑语句,在切点方法执行前调用。相当于@Before
            jp.proceed();   //执行切点方法。
            //一些逻辑语句,在切点方法执行后调用。相当于@After
        }
        catch(Throwable e)
        {
            //一些逻辑语句,在切点方法抛出异常后调用.相当于@AfterThrowing。
        }
    }
}

处理通知中的参数:

@before(execution(** com.Performance.perform(int)) and args(参数名)
public void getParam(int 参数名1)  //切点生命了传递给通知方法的参数
{
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值