Spring AOP代码笔记

底层原理

AOP底层为动态代理模式,有两种方式:JDK代理、CGLIB代理

jdk代理:基于接口的动态代理技术

条件:必须有接口
生成的动态代理对象和被代理对象为兄弟管理

cglib代理:基于父类的动态代理技术

条件:被代理对象不能使用final修饰
导入cglib坐标
生成的动态代理对象是被代理对象的子类

在这里插入图片描述

Spring的AOP简介

思想:面向切面编程
目的:代码之间的解耦,不破坏源码的前提下,对代码进行增强(增加业务)
底层:动态代理

AOP相关术语:

aop术语:
Target(目标对象): 要被增强的对象(UserServiceImpl)
Proxy(代理对象) : 增强的对象 (proxy_obj)
Joinpoint(连接点): 可以被增强的方法(save delete update find)
Pointcut(切入点): 要开始对连接点增强(save delete)
Advice(通知/增强): 增强的业务
前置通知、后置通知、异常通知、最终通知
Aspect(切面): 切入点+通知=切面 (目标方法和增强方法合成在一起 叫做切面)
Weaving(织入):通知整合切入点形成切面的过程 我们称之为织入
形成的最终结果是一个切面 (底层实现技术就是动态代理)

AOP开发:基于XML开发、基于注解开发

基于XML的AOP开发

1.pom导入依赖

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

代码:

<!--通知类-->
        <bean id="adviceConfig" class="cn.itcast.advice.AdviceConfig"></bean>
        <!--spring的aop:
                       关注点1:通知(增强方法)
                       关注点2:织入(将通知和切入点合并成切面的过程) 使用aop标签
                                // 将增强方法和目标方法合同在一起的过程

        -->


        <!--aop的置入-->
         <aop:config>
                 <!--指向通知-->
                 <aop:aspect ref="adviceConfig">
                         <!--
                                before:之前
                                method:通知类中的某个方法
                                pointcut:指向的是切入点(要增强的方法)

                                表达式:
                                    execution(public void cn.itcast.serviceimpl.AccountServiceImpl.save(..))
                                修饰符:可以省略不写
                                返回值:可以使用通配符
                                包名:cn.itcast.serviceimpl
                                         可以使用通配符代替 但是只能代替一个

                                类名:AccountServiceImpl
                                         可以使用通配符代替 但是只能代替一个

                                方法名:save(..)
                                          可以使用通配符代替 但是只能代替一个

                                       通配符:* 可以代替所有
                                        ..:用于方法参数  用于包名
                                        方法参数:代表参数可有可无
                                        包名:cn.. 带表cn下的所有子包 cn.itcast.. 带表是cn.itcast下的所有子包
                         -->
                        <!--抽取切入点-->
                        <aop:pointcut id="pt" expression="execution(* cn.itcast.*.AccountServiceImpl.*(..))"></aop:pointcut>

                        <!--前置 后置  异常 最终 顺序无序 建议单独使用-->
                        <aop:before method="before" pointcut-ref="pt"></aop:before>
                        <aop:after-returning method="afterReturning" pointcut-ref="pt"></aop:after-returning>
                        <aop:after-throwing method="afterThrowing" pointcut-ref="pt"></aop:after-throwing>
                        <aop:after method="after" pointcut-ref="pt"></aop:after>

                        <!--环绕通知-->
                       <!-- <aop:around method="around" pointcut="execution(public void cn.itcast.serviceimpl.AccountServiceImpl.save(..))"></aop:around>-->
                 </aop:aspect>
         </aop:config>
基于注解的AOP开发

1.application.xml中开启aop的注解

<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

2.在通知类中添加注解

@Component //放在ioc容器中
@Aspect //声明当前类是一个通知类
public class AdviceConfig {
  ....
}

3.在通知方法上添加切入点表达式(也可先不加)

public class AdviceConfig {


    /*抽取切入点表达式:
    *       定义无参无返回值无内容的方法
    *               在方法头上加统一注解:@Pointcut("execution(* cn.itcast.*.AccountServiceImpl.save(..))")
    *                谁用谁调方法名
    *
    * */
    @Pointcut("execution(* cn.itcast.*.AccountServiceImpl.save(..))")
    public void pt(){}

    //通知
    //@Before("pt()")
    public void before(){
        System.out.println("之前。。。");
    }

    //通知
    
  	//@AfterReturning("pt()")
    public void afterReturning(){
        System.out.println("之后。。。");
    }

    //通知
    //@AfterThrowing("pt()")
    public void afterThrowing(){
        System.out.println("异常。。。");
    }

    //通知
    //@After("pt()")
    public void after(){
        System.out.println("最终。。。");
    }


    // 通知--给环绕用
    @Around("pt()")
    public void around(ProceedingJoinPoint pj){

        try {
            // 之前
            System.out.println("之前。。。");
            // 原方法
            pj.proceed(); //invoke
            // 之后
            System.out.println("之后。。。");

        }catch (Throwable e){
            e.printStackTrace();
            System.out.println("异常。。。");
        }finally {
            System.out.println("最终。。。");
        }
    }
}

4.抽取切入点表达式

/*抽取切入点表达式:
    *       定义无参无返回值无内容的方法
    *               在方法头上加统一注解:@Pointcut("execution(* cn.itcast.*.AccountServiceImpl.save(..))")
    *                谁用谁调方法名
    *
    * */
    @Pointcut("execution(* cn.itcast.*.AccountServiceImpl.save(..))")
    public void pt(){}
    
    
     // 通知--给环绕用
    @Around("pt()")
    public void around(ProceedingJoinPoint pj){

        try {
            // 之前
            System.out.println("之前。。。");
            // 原方法
            pj.proceed(); //invoke
            // 之后
            System.out.println("之后。。。");

        }catch (Throwable e){
            e.printStackTrace();
            System.out.println("异常。。。");
        }finally {
            System.out.println("最终。。。");
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值