Java框架_Spring5_day07_AOP(面向切面编程)

目录

九、Spring 中的 AOP

9.1 AOP 的细节

9.1.1 AOP 的相关术语

9.2 Spring 的 AOP 配置

9.2.1 applicationContext.xml

9.2.2 切入点表达式的写法

9.2.3 配置文件的修改

9.3 Spring AOP 的五种通知类型(使用XML)

9.3.1 Logger.java

9.3.2 applicationContext.java

9.4 Spring AOP 的注解方式配置五种通知类型

9.4.1 Logger.java

9.4.2 ConfigurationContext.java


九、Spring 中的 AOP

9.1 AOP 的细节

9.1.1 AOP 的相关术语

Joinpoint(连接点): (方法)

       所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点。

       目标对象中的所有方法,就是连接点。

Pointcut(切入点): (方法)

       所谓切入点是指我们要对哪些Joinpoint进行拦截的定义。

       目标对象中的某些方法:被增强的方法就是切入点。

Advice(通知/增强): (方法)

       所谓通知是指拦截到Joinpoint之后所要做的事情就是通知。

       通知的类型:前置通知,后置通知,异常通知,最终通知,环绕通知。

       需要增强的方法就是通知。

Target(目标对象):

       代理的目标对象。

Weaving(织入): 

       是指把增强应用到目标对象来创建新的代理对象的过程。

       spring采用动态代理织入,而AspectJ采用编译期织入和类装载期织入。

Proxy(代理):

       一个类被AOP织入增强后,就产生一个结果代理类。

Aspect(切面): (类)

       是切入点和通知(引介)的结合。

       通知的方法需要放置到一个类中,该类就是切面。

Introduction(引介): 

       引介是一种特殊的通知在不修改类代码的前提下, Introduction可以在运行期为类动态地添加一些方法或Field。

9.2 Spring 的 AOP 配置

【需求】在访问 AccountServiceImpl.java 中的方法之前,添加日志操作

9.2.1 applicationContext.xml

    <!--创建Service(目标对象)-->
    <bean id="accountService" class="com.cpz.service.impl.AccountServiceImpl"></bean>
    <!--spring的aop配置,明确切面(类)、通知(方法)、切入点(方法)-->
    <!--创建Logger(没有灵魂的切面)-->
    <bean id="logger" class="com.cpz.utils.Logger"></bean>
    <!--引入aop的空间,配置spring的aop-->
    <aop:config>
        <!--2:配置切入点
                expression:定义切入点的表达式
                    参数一:访问修饰符(非必填)
                    参数二:返回值(必填)
                    参数三:包名.类名(非必填),建议写上,如果不写,认为所有的类都是切入点
                    参数四:方法名(参数)(必填)
                    参数五:异常(非必填)

                              访问修饰符  返回值  包名.包名.包名...类名.方法名(参数列表)

            -->
        <aop:pointcut id="myPointcut" expression="execution(public void com.cpz.service.impl.AccountServiceImpl.saveAccount())"></aop:pointcut>
        <!--<aop:pointcut id="myPointcut1" expression="execution(public void com.cpz.service.impl.AccountServiceImpl.updateAccount(int))"></aop:pointcut>-->
        <!--<aop:pointcut id="myPointcut2" expression="execution(public int com.cpz.service.impl.AccountServiceImpl.deleteAccount())"></aop:pointcut>-->

        <!--1:配置切面(有灵魂的切面)-->
        <aop:aspect id="myAspect" ref="logger">
            <!--3:配置通知(前置通知:表示在访问目标对象方法之前,执行通知)
                method="":通知的方法名称
            -->
            <aop:before method="printLog" pointcut-ref="myPointcut"></aop:before>
            <!--<aop:before method="printLog" pointcut-ref="myPointcut1"></aop:before>-->
            <!--<aop:before method="printLog" pointcut-ref="myPointcut2"></aop:before>-->
        </aop:aspect>
    </aop:config>

9.2.2 切入点表达式的写法

切入点表达式的写法​ 关键字:execution(表达式)​ 表达式:

       参数一:访问修饰符(非必填)

       参数二:返回值(必填)

       参数三:包名.类名(非必填)

       参数四:方法名(参数)(必填)

       参数五:异常(非必填)​ 访问修饰符 返回值 包名.包名.包名...类名.方法名(参数列表)

标准的表达式写法:
     public void com.cpz.service.impl.AccountServiceImpl.saveAccount()

访问修饰符可以省略
     void com.cpz.service.impl.AccountServiceImpl.saveAccount()
     返回值可以使用通配符(*:表示任意),表示任意返回值
        * com.cpz.service.impl.AccountServiceImpl.saveAccount()
     包名可以使用通配符,表示任意包。但是有几级包,就需要写几个*.
        * *.*.*.*.AccountServiceImpl.saveAccount())
     包名可以使用..表示当前包及其子包
        * *..AccountServiceImpl.saveAccount()
     类名和方法名都可以使用*来实现通配(一般情况下,不会这样配置)
                    * *..*.*() == * *()
     参数列表:
          可以直接写数据类型:
             基本类型直接写名称           int
             引用类型写包名.类名的方式     java.lang.String
                    可以使用通配符表示任意类型,但是必须有参数
                    可以使用..表示有无参数均可,有参数可以是任意类型
     全通配写法:* *..*.*(..)

实际开发中切入点表达式的通常写法:切到业务层实现类下的所有方法:* com.cpz.service..*.*(..)

9.2.3 配置文件的修改

    <aop:config>
        <aop:pointcut id="myPointcut" expression="execution(* com.cpz.service..*.*(..))"></aop:pointcut>
        <aop:aspect id="myAspect" ref="logger">
            <aop:before method="printLog" pointcut-ref="myPointcut"></aop:before>
        </aop:aspect>
    </aop:config>

9.3 Spring AOP 的五种通知类型(使用XML)

前置通知、后置通知、异常通知、最终通知、环绕通知。

9.3.1 Logger.java

package com.cpz.utils;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

public class Logger {

    // 前置通知
    public void beforePrintLog(JoinPoint jp){
        System.out.println("前置通知  类名:" + jp.getSignature().getDeclaringTypeName().getName() + ",  方法名:" + jp.getSignature().getName());
    }

    // 后置通知
    public void afterReturningPrintLog(JoinPoint jp){
        System.out.println("后置通知  类名:" + jp.getSignature().getDeclaringTypeName().getName() + ",  方法名:" + jp.getSignature().getName());
    }

    // 异常通知
    public void afterThrowingPrintLog(JoinPoint jp){
        System.out.println("异常通知  类名:" + jp.getSignature().getDeclaringTypeName().getName() + ",  方法名:" + jp.getSignature().getName());
    }

    // 最终通知
    public void afterPrintLog(JoinPoint jp){
        System.out.println("最终通知  类名:" + jp.getSignature().getDeclaringTypeName().getName() + ",  方法名:" + jp.getSignature().getName());
    }

    // 环绕通知
    public Object aroundPrintLog(ProceedingJoinPoint pjp){
        Object returnValue = null;
        try{
            beforePrintLog(pjp);
            returnValue = pjp.proceed(pjp.getArgs());
            afterReturningPrintLog(pjp);
            return returnValue;
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            afterThrowingPrintLog(pjp);
        } finally {
            afterPrintLog(pjp);
        }
        return returnValue;
    }


}

9.3.2 applicationContext.java

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

    <bean id="accountService" class="com.cpz.service.impl.AccountServiceImpl"></bean>

    <bean id="logger" class="com.cpz.utils.Logger"></bean>

    <aop:config>
        <aop:pointcut id="myPointcut" expression="execution(* com.cpz.service..*.*(..))"></aop:pointcut>
        <aop:aspect id="myAspect" ref="logger">
            <!--<aop:before method="beforePrintLog" pointcut-ref="myPointcut"></aop:before>-->
            <!--<aop:after-returning method="afterReturningPrintLog" pointcut-ref="myPointcut"></aop:after-returning>-->
            <!--<aop:after-throwing method="afterThrowingPrintLog" pointcut-ref="myPointcut"></aop:after-throwing>-->
            <!--<aop:after method="afterPrintLog" pointcut-ref="myPointcut"></aop:after>-->
            <aop:around method="aroundPrintLog" pointcut-ref="myPointcut"></aop:around>
        </aop:aspect>
    </aop:config>

</beans>

9.4 Spring AOP 的注解方式配置五种通知类型

9.4.1 Logger.java

package com.cpz.utils;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Component(value = "logger")
@Aspect
public class Logger {

    @Pointcut("execution(* com.cpz.service..*.*(..))")
    private void myPointcut(){}

    // 前置通知
    //@Before(value = "myPointcut()")
    public void beforePrintLog(JoinPoint jp){
        System.out.println("前置通知  类名:" + jp.getSignature().getDeclaringTypeName() + ",  方法名:" + jp.getSignature().getName());
    }

    // 后置通知
    //@AfterReturning(value = "myPointcut()")
    public void afterReturningPrintLog(JoinPoint jp){
        System.out.println("后置通知  类名:" + jp.getSignature().getDeclaringTypeName() + ",  方法名:" + jp.getSignature().getName());
    }

    // 异常通知
    //@AfterThrowing(value = "myPointcut()")
    public void afterThrowingPrintLog(JoinPoint jp){
        System.out.println("异常通知  类名:" + jp.getSignature().getDeclaringTypeName() + ",  方法名:" + jp.getSignature().getName());
    }

    // 最终通知
    //@After(value = "myPointcut()")
    public void afterPrintLog(JoinPoint jp){
        System.out.println("最终通知  类名:" + jp.getSignature().getDeclaringTypeName() + ",  方法名:" + jp.getSignature().getName());
    }

    // 环绕通知
    @Around(value = "myPointcut()")
    public Object aroundPrintLog(ProceedingJoinPoint pjp){
        Object returnValue = null;
        try{
            beforePrintLog(pjp);
            returnValue = pjp.proceed(pjp.getArgs());
            afterReturningPrintLog(pjp);
            return returnValue;
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            afterThrowingPrintLog(pjp);
        } finally {
            afterPrintLog(pjp);
        }
        return returnValue;
    }


}

9.4.2 ConfigurationContext.java

package com.cpz.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@ComponentScan(basePackages = "com.cpz")
@EnableAspectJAutoProxy
public class ConfigurationContext {

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值