Spring AOP :面向切面编程
代理最小范围是方法,可以针对指定类,或指定名称的方法进行代理,支持通配符 add*()。
Aop的概念:
1: 切入点:(在烧饼的什么地方切开):在哪些类,哪些方法上切入其他代码(功能增强)
2:增强(通知):(需要放到烧饼中的肉) 在执行原有方法的什么时候(方法前,方法后)要去做什么(插入需要增加的代码)
3:切面: 切入点+增强 在哪些类,哪些方法执行的过程中插入需要增加的代码。
4:织入:(将肉放到烧饼中的过程),把切面加入到对象中,并且创建出代理对象的过程(该过程由Spring自动完成)
Spring AOP的两种实现方法:
1: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"
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">
<!-- 从指定包下的注解 -->
<context:component-scan base-package="com.zhiyou"/>
<!--开启后允许使用 Spring AOP 的@AspectJ 注解 如果是纯 xml 配置 可以不用开启这个声明-->
<aop:aspectj-autoproxy/>
<!-- 1.配置目标对象 -->
<bean name="orderService" class="com.zhiyou.service.UserServiceImpl"/>
<!-- 2.声明切面 -->
<bean name="myAdvice" class="com.zhiyou.advice.CustomAdvice"/>
<!-- 3.配置将通知织入目标对象 -->
<aop:config>
<!--命名切入点 关于切入点更多表达式写法可以参见 README.md-->
<aop:pointcut expression="execution(* com.zhiyou.service.OrderService.*(..))" id="cutPoint"/>
<aop:aspect ref="myAdvice">
<!-- 前置通知 -->
<aop:before method="before" pointcut-ref="cutPoint"/>
<!-- 后置通知 如果需要拿到返回值 则要指明返回值对应的参数名称-->
<aop:after-returning method="afterReturning" pointcut-ref="cutPoint" returning="result"/>
<!-- 环绕通知 -->
<aop:around method="around" pointcut-ref="cutPoint"/>
<!-- 后置异常 如果需要拿到异常 则要指明异常对应的参数名称 -->
<aop:after-throwing method="afterException" pointcut-ref="cutPoint" throwing="exception"/>
<!-- 最终通知 -->
<aop:after method="after" pointcut-ref="cutPoint"/>
</aop:aspect>
</aop:config>
</beans>
1.2:切面表达式
切面表达式遵循以下格式
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern)throws-pattern?)
1.3 切面AOPUtil类
package com.zhiyou.util;
import org.aspectj.lang.ProceedingJoinPoint;
public class AopUtil {
public void save() {
System.out.println("在方法执行前进行增强操作");
}
public void after() {
System.out.println("在方法执行之后进行增强操作");
}
public void after2() {
System.out.println("普通后置增强");
}
public void throwingAfter() {
System.out.println("在方法执行过程中出现异常执行的代码");
}
}
2.注解实现
2.1: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: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-4.3.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<!-- 开启注解扫描 -->
<context:component-scan base-package="com.zhiyou"/>
<!-- 开启aop注解方式,这样java类中的aop注解才会生效 -->
<aop:aspectj-autoproxy/>
</beans>
2.2:切面AOPUtil2类
package com.zhiyou.util;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect // 修饰类,用来表示这个类是一个切面
public class AopUtil2 {
@Pointcut("execution(* com.zhiyou.service..*.add*(..))")
public void asjkdhka() {//配置这个方法为切点
}
@Around("asjkdhka()")
public Object around(ProceedingJoinPoint pjp){
System.out.println("开启事务------ 前置增强");
Object obj=null;
try {
obj=pjp.proceed(); // 调用正常的业务方法
System.out.println("正常执行,提交事务");
}catch (Throwable e) {
System.out.println("出现错误,回滚事务");
}finally {
System.out.println("关闭资源");
}
return obj;
}
}