什么是Aop
是将项目中的方法素有的共通性的代码提取出来 形成一个切面类 直接插入到 方法中 形成了解耦 以及增加代码的左右
它可以不修改原有代码的情况 增强原有组件的功能
将共同业务逻辑 提取到切面中 有利于 切面 和 组件 解耦 提供组件和切面的复用程度 提高程序灵活性。
AOP的概念
Aspect 切面 封装共通业务逻辑的 封装共通业务逻辑的类叫切面类 用切面类创建的
对象 叫切面对象。
JoinPoint 连接点 用来说明共通业务逻辑 所嵌入的位置 一般封装了方法的信息
PointCut 切点 多个连接点 组成的一个集合 (后面会讲用表达式来表达切点)
Target 目标 要加强的对象
Proxy 代理 增强之后的对象
Advice 通知 时机 目标方法调用之前 目标方法调用之后 目标方法调用前后 目标方法最终
目标方法出现异常
切面 --------- 通知 ------------- 切点
基于配置文件形式实现Aop
简单案例 在Serviec输出方法中 加入 输出时间的方法 不修改原有逻辑
service代码
@Service
public class TestService {
public void test1(){
System.out.println("123");
}
public void test2(){
System.out.println("123");
}
}
切面类代码 (增加代码)
public class TestAs {
public void start(){
System.out.println("********");
}
}
配置文件 配置Aop 将 切面类插入方法 方法执行后执行切面类方法
<aop:config>
<aop:aspect ref="testService "> //aop的归属类
<aop:after method="start" pointcut="bean(testService )"/> //after 在插入方法之后 method 执行的方法 pointcut 插入的类
</aop:aspect>
</aop:config>
<?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:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.1.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.1.xsd">
//开启注解形式扫描
<context:component-scan base-package="com.liheng"></context:component-scan>
//将切面类加入到ioc容器中
<bean id="as" class="com.test.as.TestAs"></bean>
//配置 aop配置
<aop:config>
//aop的归属类
<aop:aspect ref="testService ">
//after 在插入方法之后 method 执行的方法 pointcut 插入的类
<aop:after method="start" pointcut="bean(testService )"/>
</aop:aspect>
</aop:config>
</beans>
切点表达式的写法
bean限定
bean(bean对象在容器的id) 支持统配 如 *dao
类型限定表达式
within(类型限定) 表达式中最后一部分必须是类型
方法限定表达式
execution(方法限定表达式)
方法限定表达式的构成是 权限修饰 方法返回值类型 方法名(参数列表) throws 异常
注意 方法返回值 方法名() 是必须的 其它可选
void *Account()
Spring 中的五种通知类型
<aop:before 前置通知 目标方法调用前执行
<aop:after 最终通知 目标方法调用后 肯定会执行
<aop:after-returning 后置通知 目标方法调用后 执行
<aop:after-throwing 异常通知 目标方法出现异常后执行
<aop:around 环绕通知 逻辑是整体时 推荐使用环绕通知
注解形式实现Aop
在配置文件中开启标注形式Aop
开启组件扫描
案例 实现方法的异常日志
配置文件 配置Aop 注解形式
<aop:aspectj-autoproxy proxy-target-class=“true”></aop:aspectj-autoproxy>
proxy-target-class=“true” 默认是 false 是 sun公司开启代理 false是cglib公司
<?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:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.1.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.1.xsd">
//开启注解方式
<context:component-scan base-package="com.liheng"></context:component-scan>
//开启mvc注解
<mvc:annotation-driven></mvc:annotation-driven>
//开启注解形式Aop
<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>
</beans>
Aop切面类实现
//将当前类加入到容器中
@Component
//将当前类设置为切面类
@Aspect
public class DaoAs {
SimpleDateFormat sim = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
//在 testDao类所有方法执行前 执行此方法
@Before("bean(testDao)")
public void add(){
System.out.println(sim.format(new Date()));
}
//当方法出现异常 输出时间 方法的名称 以及出现的异常
//throwing="e" 需要接收方法的异常 转换成e e异常类
//JoinPoint 可以接收到 方法的名称
@AfterThrowing(pointcut="bean(testDao)",throwing="e")
public void exceptionLog(JoinPoint pj,Exception e){
System.out.println(sim.format(new Date())+"\\"+pj.getSignature()+"\\"+e);
}
//环绕通知 通过ProceedingJoinPoint 类可以执行 即将要调用的方法 返回的就是执行的方法需要将返回的方法Return
@Around("execution(void *User())")
public Object time(ProceedingJoinPoint pjj) throws Throwable{
long startTime = System.currentTimeMillis();
Object o = pjj.proceed();
long endTime = System.currentTimeMillis();
System.out.println(pjj.getSignature()+"执行"+(endTime-startTime)+"毫秒");
return o;
}
}
五种通知对应的标注
<aop:before 前置通知 目标方法调用前执行 @Before
<aop:after 最终通知 目标方法调用后 肯定会执行 @After
<aop:after-returning 后置通知 目标方法调用后 执行 @AfterReturning
<aop:after-throwing 异常通知 目标方法出现异常后执行 @AfterThrowing
<aop:around 环绕通知 逻辑是整体时 推荐使用环绕通知 @Around