Spring框架--AOP面向切面编程
Posted 肖帆咪
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring框架--AOP面向切面编程相关的知识,希望对你有一定的参考价值。
Spring框架往期文章
- Spring框架(一)–spring搭建和IOC
- Spring框架(二)–Spring Bean管理
- Spring框架(三)–Spring JDBC
- Spring框架(四)–AOP面向切面编程
- Spring框架(五)–Spring事务管理和Spring事务传播行为
AOP(Aspect Oriented Programming 面向切面编程)
不使用 AOP 的开发方式的例子
先定义好接口与一个实现类,该实现类中除了要实现接口中的方法外,还要再写两个非业务方法。非业务方法也称为交叉业务逻辑:
不使用aop,我们需要显式调用
AOP概述
AOP是OOP的延续,利用AOP可以对业务逻辑的各个部分进行隔离,降低业务逻辑部分间的耦合度,提高代码的重用性和开发效率
AOP和OOP的关系:
OOP是针对业务处理过程的实体及其属性,行为进行抽象封装,使得更加清晰高效的逻辑单元划分
AOP是针对业务处理过程中的切面进行提取,面对的是某个步骤或者阶段,以获得逻辑过程中各部分间低耦合的隔离效果
原理 😗 使用动态代理的方式在执行方法前后加入相关逻辑
案例😗 事务处理:开启/关闭事务,出现异常后回滚事务
权限判断:在执行方法前,判断是否具有权限
日志:在执行前进行日志处理
AOP的基本概念
连接点(joinpoint)😗 类中可以被增强的方法(添加额外的功能)
切入点(pointcut)😗 类中很多方法可以被加强,若实际只有add被增强了,那么add方法就是切入点
通知(Advice)😗 一个切面在特定的连接点需要做的事
切面(Aspect)😗 把通知添加到切入点的过过程
目标(Target)😗 代理的目标对象(要增强的类)
代理(Proxy)😗 向目标对象应用通知之后创建的代理对象
springAOP 实现
AspectJ 实现了 AOP 的功能,AspectJ 是一个基于 Java 语言的 AOP框架,它提供了强大的 AOP 功能,且其实现方式更为简捷,使用更为方便,而且还支持注解式开发。所以,Spring 又将 AspectJ 的对于 AOP 的实现也引入到了自己的框 架中。
在 Spring 中使用 AOP 开发时,一般使用 AspectJ 的实现方式。
AspectJ 是一个优秀面向切面的框架,它扩展了 Java 语言,提供了强大的切面实现。
AspectJ 中常用的通知有五种类型:前置通知,后置通知,环绕通知,异常通知,最终通知.
1.下载 AOP 相关 jar
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
2.基于 aspectj 的 xml 配置方式实现
<?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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
">
<bean id="aopdemo" class="com.ff.spring.aop.AopDemo"></bean>
<aop:config>
<!-- 配置切入点 -->
<aop:pointcut expression="execution(*com.ff.spring.service.UserService.adduser(..))" id="adduser"/>
<aop:pointcut expression="execution(*com.ff.spring.service.UserService.*(..))" id="allmethod"/>
<!-- 配置通知和切入点 -->
<aop:aspect ref="aopdemo">
<aop:before method="savelog" pointcut-ref="adduser"/>
<aop:after method="savelog" pointcut-ref="adduser"/>
</aop:aspect>
</aop:config>
</beans>
3.环绕通知和异常通知特殊
<?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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
">
<bean id="aopdemo" class="com.ff.spring.aop.AopDemo"></bean>
<aop:config>
<!-- 配置切入点 -->
<aop:pointcut expression="execution(*com.ff.spring.service.UserService.adduser(..))" id="adduser"/>
<aop:pointcut expression="execution(*com.ff.spring.service.UserService.*(..))" id="allmethod"/>
<!-- 配置通知和切入点 -->
<aop:aspect ref="aopdemo">
<aop:around method="aroundAdvice" pointcut-ref="adduser"/>
<aop:after-throwing method="exceptionAdvice" pointcut-ref="allmethod"throwing="e" />
</aop:aspect>
</aop:config>
</beans>
切面类
package com.spring0.common;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
public class Common {
/*
环绕通知:需要传入ProceedingJoinPoint
使用ProceedingJoinPoint对象代理调用方法
*/
public void trans(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("开启事务");
proceedingJoinPoint.proceed();//代理调用我们的业务代码
System.out.println("提交事务");
}
/*
异常通知
*/
public void exception(Throwable e){
System.out.println("出错了"+e.getMessage());
}
}
使用注解实现AOP
1.在spring.xml中添加开启<aop:aspectj-autoproxy />
2.在切面类中加注解@Component@Aspect
3.在方法前加注解
package com.spring0.common;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
/*
1.在spring.xml中添加开启<aop:aspectj-autoproxy />
2.在切面类中加注解
@Component
@Aspect
3.在方法前加注解
*/
@Component
@Aspect
public class Common {
/*
通知:在连接点上做的事情
通知类型:前置通知,后置通知,环绕通知,异常通知,最终通知
*/
// @Before("execution(* com.spring0.dao.UserDao.save(..))")注解方式的前置通知
//注解方式的后置通知
@After("execution(* com.spring0.dao.UserDao.save(..))")
public void saveLog(){
System.out.println("保存日志");
}
/*
环绕通知
注解方式:@Around("execution(* com.spring0.dao.UserDao.save(..))")
*/
@Around("execution(* com.spring0.dao.UserDao.save(..))")
public void trans(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("开启事务");
proceedingJoinPoint.proceed();//代理调用我们的业务代码
System.out.println("提交事务");
}
/*
异常通知
注解方式@AfterThrowing(value = "execution(* com.spring0.dao.UserDao.save(..))" , throwing = "e")
*/
@AfterThrowing(value = "execution(* com.spring0.dao.UserDao.save(..))" , throwing = "e")
public void exception(Throwable e){
System.out.println("出错了"+e.getMessage());
}
}
以上是关于Spring框架--AOP面向切面编程的主要内容,如果未能解决你的问题,请参考以下文章