学习AOP,看这一篇就够了

一、AOP概述

        1.概念:

                AOP(Aspect Oriented Programming)面向切面编程

        2.作用:

                在不惊动源代码的情况下,增强功能      恰好体现了spring的理念:无入侵式 

        3.核心概念:

                连接点(JoinPoint):程序执行过程中的任意位置。在springAop中,理解为所有的方法
                切入点(PointCut):匹配连接点的式子。在SpringAop中代表需要增强功能的方法,一个

                切入点可以是一个方法或者是多个方法。
                例如:一个方法:在com.zr包下孙平这个类中,一个无参无返回值的RUN方法
                           多个方法:所有的RUN方法
                 通知:就是将共性功能抽出来定义成一个方法,会在切入点处执行
                 通知类:定义通知方法的类
                 切面:描述通知与切入点的对应关系

二、小案例促进理解(在切入点输出当前系统时间)

        1.导入依赖

        2.制作连接点

        在数据层中创建数据接口和数据实现类,并在数据实现类中定义连接点:

          3.制作通知类和通知

          将输出系统当前时间的语句封装成一个类中的方法,这个类就是通知类,这个方法就是通知

        4.定义切入点

@Pointcut("execution(void Dao.BookDao.update())")
   				 private void  pt(){}
说明:切入点定义依托一个不具有实际意义的方法进行,即无参数,无返回值,无方法体,无实际逻辑
		

        这里插一下AOP切入点表达式小知识:

        剖析一下:execution(void Dao.BookDao.update())
            1.动作关键字:execution(表示执行,不可省略)
            2.访问修饰符:public private 等可以省略
            3.返回值:如果是其他类型的返回值就写其他类型的返回值,这里的Void代表无返回值。如果是环绕通知的话,这里要把void改成Object,且返回值不可省略
            4.包名:可以写也可以用*号代表任意
            5.类/接口名:可以写也可以用*代表任意,也可以当做前缀或者后缀。例如:*Service代表以Service结尾的任意类/接口,T*代表以T开头的任意类/接口。
            6.方法名:可以写也可以用*代表任意,也可以当做前缀或者后缀。例如:*Service代表以Service结尾的任意方法,T*代表以T开头的任意方法。
            7.参数:可以写也可以用*或者..代表任意参数。*代表单个任意参数,..代表多个任意参数
            8.异常名:方法定义中抛出指定异常,可以省略

        5.定义切面

         这里我用到的是前置通知类型:

        这里插一下AOP五大通知类型的小tips:

             (1).前置通知:在遇到切入点时,在他前面执行通知语句

  @Pointcut("execution(void com.zr.Dao.BookDao.update())")
    private void  pt(){}

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


               (2).后置通知:在遇到切入点时,在他后面执行通知语句

 @Pointcut("execution(void com.zr.Dao.BookDao.update())")
    private void  pt(){}

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


               (3).环绕通知(重点):

  @Pointcut("execution( public void com.zr.dao.BookDao.select())")
            private void pt(){}

         @Around("pt()")
            public void around(ProceedingJoinPoint pjp) throws Throwable {
                System.out.println("around before advice ....");
                pjp.proceed();
                System.out.println("around after advice ....");
            }

     说明:
    1.环绕通知必须依赖形参ProceedingJoinPoint 才能实现对原始方法的调用,进而实现原始方法调用前后同时添加通知
    2.环绕通知中如果未使用ProceedingJoinPoint 形参对原始方法进行调用将跳过原始方法的执行,会造成原始操作隔离(可以进行权限校验)
        比如:你是经理权限才可以对原始方法进行操作,你不是经理不能对原始方法操做
    3.对原始方法的调用可以不接收返回值,通知方法设置为void即可,如果接受返回值的话,必须设定为Object
    4.由于无法预知原始方法运行后是否抛出异常,因此环绕通知方法必须抛出异常对象
               (4)返回后通知(了解)

public class CommentCode {
    @Pointcut("execution(void com.zr.Dao.BookDao.update())")
    private void  pt(){}

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


               (5)抛出异常后通知(了解);

public class CommentCode {
    @Pointcut("execution(void com.zr.Dao.BookDao.update())")
    private void  pt(){}

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

        6.定义配置类:

@Configuration
@ComponentScan("com.zr")
@EnableAspectJAutoProxy  //有这句注解才能启动CommentCode类中的@Aspect注解
public class SpringConfig {
}


        7.编写测试类:

public class APP {
    public static void main(String[] args) {
        ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        BookDao bean = ctx.getBean(BookDao.class);
        bean.update();
    }
}

        8.测试结果;

三、注意:

        1.数据实现类一定不要忘记加注解    @Repository

        2.通知类中也不要忘记加这两个注解:

        @Component   //加这个注解意思就是把这些代码变成组件,这样的话代码就受控了,但是把代码变成组件意味着变成bean

        @Aspect   //就告诉程序以下代码不是Bean,要当AOP来处理

        3.配置类中也不要忘记加 这个注解:

        @EnableAspectJAutoProxy //有这句注解才能启动CommentCode类中的@Aspect注解

 四、拓展小知识:

        1.不知道大家有没有印象我上面提到过原始操作隔离这个概念。意思就是如果切面和切入点没有匹配成功的话,代码不会报错,但是不会得到你想要的结果。因为匹配失败后,程序就会拿着原始对象进行操作,从而不能执行原始方法,而匹配成功后程序会拿着代理对象执行原始方法的执行这也恰恰体现了SpringAop的核心本质是采用代理模式实现的。

        2.当大家听到AOP是面向切面编程,可能会想到面向对象编程和面向过程编程。那我就来说一下他们二者的区别吧:

        面向对象编程(OOP):是依赖于类和对象,他的特点是封装、继承、多态

        面向过程编程(POP):他认为程序是过程和函数的集合,他会分析出解决问题的过程中所需要的步骤,然后用函数一个个实现步骤

        举个例子吧:

        面向过程就像西红柿鸡蛋炒饭,第一步打鸡蛋,第二步切西红柿,第三步炒西红柿,第四步炒饭,第五步放之前炒好的西红柿和鸡蛋,第六步出锅
         面向对象就像西红柿鸡蛋盖饭:首先是鸡蛋对象和西红柿对象有一个mix混合方法得到西红柿炒蛋结果,然后就是大米对象有一个煮熟方法得到一个饭的结果,最后西红柿鸡蛋和饭有一个浇盖的方法得到西红柿鸡蛋盖饭
         为什么一个是炒饭一个是盖饭,因为面向对象的可维护性强,代码耦合度低,就像盖饭一样,不喜欢菜就可以换一个菜浇上去,不喜欢饭就换一个饭上去,但是你不喜欢炒饭里面的蛋的话就需要倒掉 

五、致敬:

        感谢每一个陪伴我打代码的深夜,还有我隔壁的战斗哥,每次都在我打代码的时候战斗

当然也要感谢认真看完我代码的你们咯(Salute~)

        

  • 22
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值