IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Spring(4) -> 正文阅读

[Java知识库]Spring(4)

Spring AOP(面向切面编程) 是什么?

????????面向切面编程(AOP) 和面向对象编程(OOP)类似,也是一种编程模式/编程思想。

????????有效减少了系统见的重复代码,达到了模块间的松耦合目的。

????????AOP的全程是"Aspect Oriented Programming",即面向切面编程,它将业务逻辑的各个部分进行隔离,使开发人员再编写业务逻辑时可以专心于核心业务,从而提高了开发效率。

????????程序需要---1.业务需求----需要实现的程序的具体核心功能---添加用户

? ? ? ? ? ? ? ? ? ? ? ? ? 2.系统需求---实现的程序的辅助功能---------记录系统运行日志

????????AOP采取横向抽取机制,取代了传统的纵向继承体系的重复性代码,其应用主要体现在事务处理,日志管理,权限控制,异常处理等方面

????????目前最流行的AOP框架有两个,分别为Spring AOP和AspectJ。

????????Spring AOP 使用纯Java实现,不需要专门的编译过程和类加载器,在运行期间通过代理方式【CGLlB动态代理】向目标类植入增强的代码。

????????AspectJ 是一个基于 Java 语言的 AOP 框架,从 Spring 2.0 开始,Spring AOP 引入了对 AspectJ 的支持。AspectJ 扩展了 Java 语言,提供了一个专门的编译器,在编译时提供横向代码的植入。

????????为了更好地理解 AOP,就需要对 AOP 的相关术语有一些了解,这些专业术语主要包含 Joinpoint、Pointcut、Advice、Target、Weaving、Proxy 和 Aspect,它们的含义如下表所示。

Joinpoint(连接点)指那些被拦截到的点,在 Spring 中,可以被动态代理拦截目标类的方法。
Pointcut(切入点)指要对哪些 Joinpoint 进行拦截,即被拦截的连接点。
Advice(通知)指拦截到 Joinpoint 之后要做的事情,即对切入点增强的内容。
Target(目标)指代理的目标对象。
Weaving(植入)指把增强代码应用到目标上,生成代理对象的过程。
Proxy(代理)指生成的代理对象。

Aspect(切面)

切入点和通知的结合。?

Advice(通知)指拦截到 Joinpoint 之后要做的事情,即对切入点增强的内容。

org.springframework.aop.MethodBeforeAdvice(前置通知)?? ?
在方法之前自动执行的通知称为前置通知,可以应用于权限管理等功能。

org.springframework.aop.AfterReturningAdvice(后置通知)
在方法之后自动执行的通知称为后置通知,可以应用于关闭流、上传文件、删除临时文件等功能。

org.aopalliance.intercept.MethodInterceptor(环绕通知)
在方法前后自动执行的通知称为环绕通知,可以应用于日志、事务管理等功能。

org.springframework.aop.ThrowsAdvice(异常通知)
在方法抛出异常时自动执行的通知称为异常通知,可以应用于处理异常记录日志等功能。

Spring使用AspectJ开发AOP:基于XML和基于Annotation

基于XML【Spring核心配置文件】

package com.spring.demo1.impl;

import com.spring.demo1.StudentService;

public class StudentServiceImpl implements StudentService {
    //Joinpoint(连接点)
    @Override
    public void insertStudent() {
        System.out.println("实现添加学生信息的业务方法--insert");
    }
    //Joinpoint(连接点)
    @Override
    public void updateStudent() {
        int a=10/0;
        System.out.println("实现修改学生信息的业务方法--update");
    }
    //Joinpoint(连接点)
    @Override
    public void deleteStudent() {
        System.out.println("实现删除学生信息的业务方法--delete");
    }
    //Joinpoint(连接点)
    @Override
    public void selectStudent() {
        System.out.println("实现查询学生信息的业务方法--select");
    }
}
package com.spring.demo1.aspect;

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

//系统需求功能实现类
public class MyAspect {
//系统需求功能实现方法
    public void saveLog(){
        System.out.println("记录用户的操作日志");
    }
    //实现环绕通知的具体方法
    public Object myAround(ProceedingJoinPoint proceedingJoinPoint) throws  Throwable{
        saveLog();//开始
        Object obj = proceedingJoinPoint.proceed(); // 执行当前目标方法
        saveLog();//结束
        return obj;
    }
    //异常通知实现方法
    public void myAfterThrowing(JoinPoint joinPoint,Throwable e){
        System.out.println("异常通知"+"出错了"+e.getMessage());
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       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="studentservice" class="com.spring.demo1.impl.StudentServiceImpl"></bean>
    <!-- 创建系统需求功能实现类 -->
    <bean id="myaspect" class="com.spring.demo1.aspect.MyAspect"></bean>
    <!-- aop配置 -->
    <!-- proxy-target-class="true" 设置aop使用CGLIB代理模式 -->
    <aop:config proxy-target-class="true">
        <!-- 引入系统需求功能实现类 -->
        <aop:aspect ref="myaspect">
            <!-- 配置切入点 -->
            <!--id:切入点名称-->
            <!-- expression:切入点表达式 -->
            <aop:pointcut id="point1" expression="execution(* com.spring.demo1.impl.StudentServiceImpl.insertStudent(..))"/>
            <!-- 配置前置通知 -->
            <aop:before method="saveLog" pointcut-ref="point1"></aop:before>
        </aop:aspect>

        <aop:aspect ref="myaspect">
            <!-- 配置切入点 -->
            <aop:pointcut id="point2" expression="execution(* com.spring.demo1.impl.StudentServiceImpl.deleteStudent(..))"/>
            <aop:after method="saveLog" pointcut-ref="point2"></aop:after>
        </aop:aspect>
        <aop:aspect ref="myaspect">
            <!-- 配置切入点 -->
            <aop:pointcut id="point3" expression="execution(* com.spring.demo1.impl.StudentServiceImpl.selectStudent())"/>
            <aop:around method="myAround" pointcut-ref="point3"></aop:around>
        </aop:aspect>
        <aop:aspect ref="myaspect">
            <!-- 配置切入点 -->
            <aop:pointcut id="point4" expression="execution(* com.spring.demo1.impl.StudentServiceImpl.updateStudent(..))"/>
            <aop:after-throwing method="myAfterThrowing" pointcut-ref="point4" throwing="e"></aop:after-throwing>
        </aop:aspect>
    </aop:config>
</beans>

基于Annotation

package com.spring.demo1;

import org.springframework.stereotype.Component;

@Component("student")
public class StudentServiceImpl {
    public void insertStudent(){
        System.out.println("添加学生信息的业务方法---insertStudent");
    }
    public void uodateStudent(){
        System.out.println("修改学生信息的业务方法---updateStudent");
    }
    public void deleteStudent(){
        System.out.println("删除学生信息的业务方法---deleteStudent");
    }
    public void selectStudent(){
        System.out.println("查询学生信息的业务方法---selectStudent");
        int a=10/0;
    }

}
package com.spring.demo1;

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

@Component("myAspect")
@Aspect
public class MyAspect {
    @Pointcut("execution(* com.spring.demo1.StudentServiceImpl.insertStudent())")
    public void point1(){}

    @Pointcut("execution(* com.spring.demo1.StudentServiceImpl.uodateStudent())")
    public void point2(){}

    @Pointcut("execution(* com.spring.demo1.StudentServiceImpl.deleteStudent())")
    public void point3(){}

    @Pointcut("execution(* com.spring.demo1.StudentServiceImpl.selectStudent())")
    public void point4(){}

    public void saveLog(){
        System.out.println("记录系统运行日志");
    }

    //测试前置通知
    @Before("point1()")
    public void myBefore(){
        saveLog();
    }

    //测试后置通知
    @After("point2()")
    public void myafter(){
    saveLog();
    }

    //测试环绕通知
    @Around("point3()")
    public Object myAround(ProceedingJoinPoint  proceedingJoinPoin) throws Throwable{
        saveLog();
        Object obj=proceedingJoinPoin.proceed();
        saveLog();
        return obj;
    }

    //测试异常通知
    @AfterThrowing(value = "point4()",throwing = "e")
    public void myAfterThrowing(Throwable e){
        System.out.println("异常通知"+"出错了"+e.getMessage());
    }

}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       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
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
    <!-- 扫面包含com.spring.demo1包下的所有注解 -->
    <context:component-scan base-package="com.spring.demo1"></context:component-scan>
    <!-- 使切面开始自动代理 -->
    <aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>
</beans>
package com.spring.demo1;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestMain {
    public static void main(String[] args) {
        ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
        StudentServiceImpl studentService=ac.getBean("student",StudentServiceImpl.class);
        //studentService.insertStudent();
        //测试后置通知
        //studentService.uodateStudent();
        //测试环绕通知
        //studentService.deleteStudent();
        //测试异常通知
        studentService.selectStudent();
    }
}

切入点表达式

? ? ? ? execution(modifiers-pattern??
?? ?????????????????????????ret-type-pattern?
?????????????????????????? ?declaring-type-pattern??
?????????????????????????? ?name-pattern(param-pattern) ?? ?
? ? ? ? ? ? ? ????????? ?? ?throws-pattern?)

这里的问号标识当前项可以有也可以没有,其中各项的语义如下:

? ? ? ? ? ? ? ???modifiers-pattern:方法的可见性,如public ,protected;

?????????????????ret-type-pattern : 方法的返回值类型,如int ,void等;

????????????? ? ?declaring-type-pattern:方法所在类的全路径名,如com.spring.demo1;

? ? ? ? ? ? ? ???name-pattern:方法名类型,如StudentService();

? ? ? ? ? ? ? ???param-pattern:方法的参数类型,如java.lang.String;

? ? ? ? ? ? ?? ? throws-pattern:方法抛出的异常类型,如java.lang.Exception;

如下是一个使用execution表达式的例子:

? ? ? ?execution(public * com.spring.service.BusinessObject.businessService(java.lang.String,..))

? ? ? ? 上述切点表达式将会匹配使用public修饰,返回值为任意类型,并且是com.spring.service.BusinessObject类中名称为businessService的方法,方法可以有多个参数,但是第一个参数必须是java.lang.String类型的方法。

? ? ? ? *通配符,该通配符主要用于匹配单个单词,或者是以某个此为前缀[insert*]或后缀[*Student]的单词

? ? ? ? execution(* com.spring.service.BusinessObject.*())

? ? ? ? 表示返回值为任意类型,在com.spring.service.BusinessObject类中,并且参数个数为零的方法

? ? ? ? execution(* com.spring.service.Business*.*())

? ? ? ? 表示返回值为任意类型,在com.spring.service包中,以Business为前缀的类,并且是类中参数个数为零的方法

? ? ? ? ..(两个点)通配符,该通配符表示0个或多个项,主要用于declaring-type-pattern和param-pattern中。

? ? ? ? 如果用于declaring-type-pattern中,则表示匹配当前包及其子包,如果用于param-pattern中,则表示匹配0个或多个参数。

? ? ? ?execution(* com.spring.service..*.businessService())

? ? ? ? 表示匹配返回值为任意类型,并且是com.spring.service包及其子包下的任意类的名称为businessService的方法,而且该方法不能有任何参数

????????execution(* com.spring.service.BusinessObject.businessService(java.lang.String,..))

????????表示匹配返回值为任意类型,并且是com.spring.service.BusinessObject类中的,名称为businessService的方法,而且该方法有第一个参数,并且第一个参数是java.lang.String类型。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-03-06 12:48:23  更:2022-03-06 12:51:48 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 12:02:50-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码