AOP面向切面编程

        在学习SSM框架,黑马的课程,在这里做一点笔记      

  AOP核心概念(核心本质是代理模式)

                1.连接点:程序执行中的任意位置,粒度为执行方法,抛出异常,设置变量

                        在springAop中理解为方法的执行

                2.切入点:匹配连接点的式子(切入点一定在连接点之中)

                        在springAOP中,一个切入点可以只描述一个具体方法,也可以匹配多个方法

                3.通知:在切入点执行的操作,也就是共性功能

                        在springAOP中,功能最终以方法的形式呈现

                4.通知类:定义通知的类

                5.切面:描述通知与切入点的对应关系(共性关系??)

        

                目标对象:原始功能去掉共性功能对应的类产生的对象,这种对象是无法直接完成最终工作的

                代理:目标对象无法直接完成工作,需要对其进行功能回填,通过原始功能的代理对象实现

               

入门案例思路分析

        案例设定:测定接口执行效率

        简化设定:在接口执行前输出当前系统时间

        开发模式:XML or 注解

        1.导入坐标

        

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>5.1.0.RELEASE</version>
</dependency>


<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjweaver</artifactId>
  <version>1.9.4</version>
</dependency>

        2.制作连接点方法(原始操作,Dao接口与实现类)

                目的是为了给update加上一个打印时间方法

public void save() {
    System.out.println(System.currentTimeMillis());
    System.out.println("book dao save");
}

public void update() {
    System.out.println("book dao update");
}

        3.制作共性功能

        4.定义切入点

        5.绑定切入点与通知关系(切面)

//加入到spring 控制
@Configuration
//提醒当成AOP
@Aspect
public class MyAdvice {
    //定义切入点
    @Pointcut("execution(void hammer.Dao.Impl.BookDaoimpl.update())")
    private void pt(){}

    @After("pt()")//将通知和切入点进行绑定
     //定义好通知
    public void method(){
        System.out.println(System.currentTimeMillis());
    }
}

   

AOP工作流程

1.spring容器启动

2.读取所有切面配置中的切入

@Configuration
//提醒当成AOP使用
@Aspect
public class MyAdvice {
    //定义在谁那里执行方法
    @Pointcut("execution(void hammer.Dao.Impl.BookDaoimpl.update())")
    private void pt(){}

    @Pointcut("execution(void hammer.Dao.Impl.BookDaoimpl.save())")
    private void up(){}
    @After("pt()")
    public void method(){
        System.out.println(System.currentTimeMillis());
    }
}

  3.初始化bean,判定bean对应的类中的方法是否匹配到任意切入点

        匹配失败,创建对象

        匹配成功,创建原始对象

        

//成功匹配的 造了一个代理对象
hammer.Dao.Impl.BookDaoimpl@3eb25e1a
class com.sun.proxy.$Proxy19

//匹配失败的 使用的原始对象
hammer.Dao.Impl.BookDaoimpl@36fc695d
class hammer.Dao.Impl.BookDaoimpl

4.获取bean执行方法

        获取bean,调用方法并执行,完成操作

        获取的bean是代理对象时,根据代理对象的运行模式运行原始方法与增强的内容,完成操作

AOP切入点表达式

        切入点:要进行增强的方法

        切入点表达式:要进行增强的方法的描述方式

描述方式一:执行Dao包下的BookDao实现类下的无参数的update方法
    execution("execution(void hammer.Dao.Impl.BookDaoimpl.update()")
描述方法二:执行Dao包下的bookDao接口下的无参房update方法
    execution("execuion(void hammer.Dao.BookDao.update()")

动作关键字:描述切入点的行为动作,例如execution表示执行到指定切入点

访问修饰符:public private 可以省略

返回值

报名

类/接口名

方法名

参数

异常名:

AOP中可以使用通配符描述切入点,快速描述

*:单个独立的任意符号,可以独立出现,也可以作为前缀或者后缀的匹配符出现

        

execution(public * hammer.*.UserService.find*(*))
匹配hammer包下的任意包中的UserService类或接口中所有find开头的带有参数的方法

..:多个连续的任意符号,可以独立出现,常用于简化包名与参数的书写

execution(public User com..UserService.findById(..))
匹配com包下的任意包中的UserService类或接口中所有名称为findById的方法

+:专用于匹配子类类型

        

execution(* *..*Service+.*(..))

AOP通知类型

        AOP通知描述了抽取的共性功能,根据共性功能抽取的位置不同,最终运行代码时要将其加入到合理的位置

        1.前置通知

        

 @Before("pt()")
    public void method(){
        System.out.println(System.currentTimeMillis());
    }

        2.后缀通知

  

 @After("pt()")
    public void method(){
        System.out.println(System.currentTimeMillis());
    }

        3.环绕通知

        

@Around("pt()")
    public void arount(Porceeding JoinPoint pjp) throws Throwable{
        System.out.println("around before advice");
        //表示对原始方法的调用
        pjp.proceed();
        System.out.println("around after advice");
    }

        有一个问题就是说如果方法存在返回值 ,那么就会造成一个错误

        

@Pointcut("execution(int hammer.Dao.Impl.BookDaoimpl.select())")
    private void pt2(){}


@Around("pt2()")
    public Object methods(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println(" win 1");
        proceedingJoinPoint.proceed();
        System.out.println("win2 ");
        return 1200;
    }
最下面的1200 强制换成了 select 的返回值

输出结果
 win 1
win2 
1200

1.环绕通知必须依赖形参ProceedingJoinPoint才能实现对原始方法的调用,进而实现原始方法调用前后添加通知

2.通知中如果未使用ProceedingJoinPoint对原始方法进行调用将跳过原始方法的执行

3.对原始方法的调用可以不接受返回值。 通知设置成void 即可,如果接收返回值,必须设定Object类型

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值