基于注解的AOP实现
Spring AOP允许使用基于注解的方式实现AOP,这样做可以简化Spring配置文件的臃肿代码。
元素 | 描述 |
---|---|
@Aspect | 配置切面 |
@Pointcut | 配置切点 |
@Before | 配置前置通知 |
@After | 配置后置通知 |
@Around | 配置环绕方式 |
@AfterReturning | 配置返回通知 |
@AfterThrowing | 配置异常通知 |
了解了如何使用注解配置切面、切入点和通知后,下面通过一个案例演示基于注解的AOP的实现,案例具体实现步骤如下。
(1)在chapter07项目(自己在IDEA中新建一个)的pom.xml文件中导入AspectJ框架相关JAR包的依赖,在pom.xml中添加的代码如下:
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.1</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
</dependency>
(2)在chapter07项目的src/main/java目录下创建一个com.cqust.dao包,在该包下创建接口UserDao,并在该接口中编写添加、删除、修改和查询的方法。UserDao接口具体代码如下:
package com.cqust.dao;
public interface UserDao {
public void insert();
public void delete();
public void update();
public void select();
}
(3)在com.cqust.dao包下创建UserDao接口的实现类UserDaoImpl,实现UserDao接口中的方法。
package com.cqust.dao;
public class UserDaoImpl implements UserDao{
public void insert(){
System.out.println("添加用户信息");
}
public void delete(){
System.out.println("删除用户信息");
}
public void update(){
System.out.println("更新用户信息");
}
public void select(){
System.out.println("查询用户信息");
}
}
(4)com.cqust.dao包下创建AnnoAdvice类,用于定义通知。
package com.cqust.dao;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
@Aspect
public class AnnoAdvice {
//切点
@Pointcut("execution( * com.cqust.dao.UserDaoImpl.*(..))")
public void poincut(){}
//前置通知
@Before("poincut()")
public void before(JoinPoint joinPoint){ //使用JoinPoint接口实例作为参数获得目标对象的类名和方法名
System.out.print("这是前置通知!");
System.out.print("目标类:" + joinPoint.getTarget());
System.out.println(",被织入增强处理的目标方法为:"+joinPoint.getSignature().getName());
}
//返回通知
@AfterReturning("poincut()")
public void afterReturning(JoinPoint joinPoint){//使用JoinPoint接口实例作为参数获得目标对象的类名和方法名
System.out.print("这是返回通知(方法不出现异常时调用)!");
System.out.println("被织入增强处理的目标方法为:"+joinPoint.getSignature().getName());
}
/**
* 环绕通知
* ProceedingJoinPoint是JoinPoint子接口,表示可以执行目标方法
* 1.必须是Object类型的返回值
* 2.必须接收一个参数,类型为ProceedingJoinPoint
* 3.必须throws Throwable
*/
@Around("poincut()")
public Object around(ProceedingJoinPoint point)throws Throwable{//使用ProceedingJoinPoint接口实例作为参数获得目标对象的类名和方法名
System.out.println("这是环绕通知之前的部分!");
//调用目标方法
Object object = point.proceed();
System.out.println("这是环绕通知之前的部分!");
return object;
}
//异常通知
@AfterThrowing("poincut()")
public void afterException(){
System.out.println("异常通知!");
}
//后置通知
@After("poincut()")
public void after(){
System.out.println("这是后置通知!");
}
}
需要注意的是,环绕通知必须接收一个类型为ProceedingJoinPoint的参数,返回值也必须是Object类型,且必须抛出异常。
(5)在chapter07项目的src/main/java目录下创建一个applicationContext.xml文件,在该文件中引入AOP命名空间,使用< bean >元素添加Spring 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 https://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 注册Bean -->
<bean name="userDao" class="com.cqust.dao.UserDaoImpl"/>
<bean name="AnnoAdvice" class="com.cqust.dao.AnnoAdvice"/>
<!-- 开启@aspectj的自动代理支持 -->
<aop:aspectj-autoproxy/>
</beans>
(6)在src/test/java目录下创建测试类TestAnnotation。
import com.cqust.dao.UserDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestAnnotation {
public static void main(String[] args){
ApplicationContext context = new
ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao = context.getBean("userDao",UserDao.class);
userDao.delete();
System.out.println();
userDao.insert();
System.out.println();
userDao.select();
System.out.println();
userDao.update();
}
}
在IDEA中启动TestAnnotation类,控制台的输出结果如图所示。
由运行结果可知,程序执行了AnnoAdvice类中的增强方法,表明Spring AOP实现了对目标对象的方法增强。
谢谢浏览!