Spring Aop介绍:
1.Aop介绍
Spring Aop是面向切面编程,底层是动态代理。可以实现在不改变源码的情况下,对目标方法进行增强。
Spring Aop支持声明式事务,与编程式事务相比较,声明式事务最大的优点就是不需要通过编程的方式管
理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明(或通过
基于@Transactional注解的方式),便可以将事务规则应用到业务逻辑中。
Spring Aop的典型使用场景:
1.事务管理;
2.日志记录;
3.权限控制
2.Spring Aop术语:
JoinPoint: 连接点:
所有的方法都可以是连接点;
Pointcut: 切入点:
需要进行增强的方法就是切入点;
Advice: 通知/增强 :
增强的逻辑就是通知,通知需要切入到切入点中;
通知分为:
前置通知;
后置通知;
环绕通知;
异常通知;
最终通知;
Aspect: 切面:
切入点和通知的结合就是切面;
3.Aop的使用:
1.创建工程,导入坐标依赖:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.it</groupId>
<artifactId>spring-aop</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!--Spring核心容器-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<!--SpringAOP相关的坐标-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.7</version>
</dependency>
<!--Spring整合单元测试-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<!--单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
2.创建Dao接口,定义方法;
public interface AccountDao {
void save();
Object delete();
void findAll();
void update();
void findById();
}
3.创建Dao接口的实现类,重写接口方法(在这里,这些方法就是需要进行增强的方法)
public class AccountDaoImpl implements AccountDao {
public void save() {
System.out.println("save....");
}
public Object delete() {
System.out.println("delete....");
return "success";
}
public void findAll() {
//模拟耗时
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("findAll...");
}
public void update() {
System.out.println("update....");
int i=1/0;
}
public void findById() {
System.out.println("findById.....");
int i=1/0;
}
}
4.创建切面类,类中定义增强逻辑方法:
public class MyAspect {
//前置通知,增强逻辑
public void check(){
System.out.println("权限校验。。。");
}
//后置通知,增强逻辑
public void log(Object obj){
System.out.println("日志记录。。。"+obj);
}
//环绕通知,增强逻辑
public void showTime(ProceedingJoinPoint joinPoint) throws Throwable {
//目标方法调用之前
System.out.println("调用之前的时间:"+System.currentTimeMillis());
//调用目标方法
joinPoint.proceed();
//目标方法调用之后
System.out.println("调用之后的时间:"+System.currentTimeMillis());
}
//异常通知,增强逻辑
public void throwException(Exception e){
System.out.println("异常抛出通知========"+e.getMessage());
}
//最终通知,增强逻辑
public void showFinal(){
System.out.println("最终通知。。。");
}
}
5.配置文件:
在配置文件中注册Dao实现类和切面类;
在配置文件中配置aop,在aop中配置切入点和切面,在切面中配置通知;
<?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">
<!--注册Dao-->
<bean id="accountDao" class="com.it.dao.impl.AccountDaoImpl"></bean>
<!--注册增强类-->
<bean id="myAspect" class="com.it.aspect.MyAspect"></bean>
<!--配置aop-->
<aop:config>
<!--配置切入点,目的是找到需要进行增强的方法-->
<!--
expression:表达式:
execution():固定写法
第一个 * 号:表示任意的返回值;
第二个 * 号:表示包名com.it.aspect下的任意类
第三个 * 号:表示任意方法
(..):表示方法的任意参数
-->
<aop:pointcut id="point01" expression="execution(* com.it.dao.impl.AccountDaoImpl.save(..))"></aop:pointcut>
<aop:pointcut id="point02" expression="execution(* com.it.dao.impl.AccountDaoImpl.delete(..))"></aop:pointcut>
<aop:pointcut id="point03" expression="execution(* com.it.dao.impl.AccountDaoImpl.findAll(..))"></aop:pointcut>
<aop:pointcut id="point04" expression="execution(* com.it.dao.impl.AccountDaoImpl.update(..))"></aop:pointcut>
<aop:pointcut id="point05" expression="execution(* com.it.dao.impl.AccountDaoImpl.findById(..))"></aop:pointcut>
<!--配置切面,找到对应的增强类-->
<aop:aspect ref="myAspect">
<!--配置前置通知,将增强类的增强逻辑切入到被增强的方法中-->
<aop:before method="check" pointcut-ref="point01"></aop:before>
<!--后置通知,可以获得目标方法返回参数-->
<aop:after-returning method="log" pointcut-ref="point02" returning="obj"></aop:after-returning>
<!--配置环绕通知-->
<aop:around method="showTime" pointcut-ref="point03"></aop:around>
<!--配置异常通知,可以获取异常信息-->
<aop:after-throwing method="throwException" pointcut-ref="point04" throwing="e"></aop:after-throwing>
<!--最终通知-->
<aop:after method="showFinal" pointcut-ref="point05"></aop:after>
</aop:aspect>
</aop:config>
</beans>
6.编写测试:
RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = "classpath:applicationContext.xml")
public class Test {
@Autowired
private AccountDao accountDao;
@org.junit.Test
public void fun(){
accountDao.save();
}
@org.junit.Test
public void fun02(){
accountDao.delete();
}
@org.junit.Test
public void fun03(){
accountDao.findAll();
}
//测试异常通知
@org.junit.Test
public void fun04(){
accountDao.update();
}
//测试最终通知
@org.junit.Test
public void fun05(){
accountDao.findById();
}
}