大一电子信息工程新生,请多多关照,希望能在 InfoQ 社区 记录 自己的学习历程!
【Spring 学习笔记】系列教程基于 Spring 5.2.10.RELEASE 讲解。
前面说过, Spring 的核心思想就是 IoC 和 AOP ,有关 IoC 的内容已经介绍过一部分了,接下来就来讲下 Spring 另一大重点: AOP 。
AOP ,“ Aspect Oriented Programming ”,译为“ 面向切面编程 ”,和 OOP(面向对象编程)类似, 它也是一种编程思想 。
Spring AOP 的实现原理是 代理模式 ,AOP 的作用是 通过代理类为原始类增加一些额外功能 :如日志管理、权限管理、事务管理、异常管理等一些 非业务性功能 。
与传统的公共方法不同,Spring AOP 并不是直接调用的,AOP 是通过 横向的抽取机制 实现的。它将一些 非业务的通用功能 抽取出来单独维护,并 通过配置文件或注解的形式定义这些功能 要以哪种方式作用在哪个模块中,可以在无须修改任何业务代码的基础上完成对这些通用功能的调用和修改,即 无入侵式 的。
事务与非事务功能分离,Spring AOP 还减少代码的重复,让我们更专注于专注业务逻辑代码。
目前最流行的 AOP 实现(框架)主要有两个,分别为 Spring AOP 和 AspectJ 。
SpringAOP 的开发有两种方式,XML 和 注解, 本篇文章及之后的教程都 使用注解开发 演示.
在 pom.xml 文件里添加 Spring AOP 和 AspectJ 的 jar 包依赖
org.springframework
spring-context
5.2.10.RELEASE
org.aspectj
aspectjweaver
1.9.5
复制代码
可以看到 spring-context 中已经导入了 spring-aop ,所以不需要再单独导入 spring-aop
目标接口和实现类就是所谓的 Target(目标),即要被代理的对象。
/*UserDao接口*/
public interface UserDao {
public void add();
public void delete();
public void update();
public void select();
}
/*UserDaoImpl实现类*/
@Repository
public class UserDaoImpl implements UserDao {
@Override
public void add() {
System.out.println("正在执行 UserDao 的 add 方法");
}
@Override
public void delete() {
System.out.println("正在执行 UserDao 的 delete 方法");
}
@Override
public void update() {
System.out.println("正在执行 UserDao 的 update 方法");
}
@Override
public void select() {
System.out.println("正在执行 UserDao 的 select 方法");
}
}
复制代码
通过 @Aspect 注解将一个 Bean 定义为切面。
@Component//将这个类定义成 Bean
@Aspect//将这个Bean定义为切面
public class MyAdvice {
}
复制代码
在 AspectJ 中,我们可以使用 @Pointcut 注解用来定义一个切点。
//切点方法必须是private,无返回值,无参数
@Pointcut(value ="execution(* com.bighorn.*.*Dao.*(..))")
private void pointCut() {
}
复制代码
**通知(Advice)**就是将共性功能抽取出来后形成的方法,即对切入点增强的内容
通知有很多类型:前置通知、后置通知、环绕通知、异常通知、返回通知。(插个眼在这,下篇文章详细嗦嗦)
通知注解中有一个 value 属性,value 属性的取值就是这些 通知(Advice) 所要 织入(Weaving) 的 切点(PointCut) ,它既可以是切入点表达式,也可以是切入点引用(切入点对应的方法名称)
//使用切入点引用
@Before("MyAdvice.pointCut()")
public void beforeAdvice() {
System.out.println("这是前置通知……");
}
//使用切入点表达式
@After(value ="execution(* com.bighorn.*.*Dao.*(..))")
public void afterAdvice(){
System.out.println("这是后置通知……");
}
复制代码
/*切面类(通知类)*/
@Component//将这个类定义成 Bean
@Aspect//将这个Bean定义为切面
public class MyAdvice {
//切点方法必须是private,无返回值,无参数
@Pointcut(value = "execution(* com.bighorn.*.*Dao.*(..))")
private void pointCut() {
}
//使用切入点引用
@Before("MyAdvice.pointCut()")
public void beforeAdvice() {
System.out.println("这是前置通知……");
}
//使用切入点表达式
@After(value ="execution(* com.bighorn.*.*Dao.*(..))")
public void afterAdvice(){
System.out.println("这是后置通知……");
}
}
复制代码
在 Spring 的配置类中 使用@AspectJ 注解 , 开启 AspectJ 的自动代理 ,使用 @ComponentScan 注解开启注解扫描。
/*Spring核心配置类*/
@Configuration
@ComponentScan("com.bighorn") //开启注解扫描
@EnableAspectJAutoProxy //开启 AspectJ 的自动代理
public class SpringConfig {
}
复制代码
public static void main(String[] args) throws SQLException {
//获取配置类初始化容器
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
//从容器中获取UserDao对象
UserDao userDao = context.getBean(UserDao.class);
//调用userDao的方法
userDao.add();
userDao.delete();
userDao.update();
userDao.select();
}
复制代码
运行结果如下,可以发现对每个方法都进行的加强:前置通知和后置通知
感谢观看啦
有什么不足,欢迎指出哦
留言与评论(共有 0 条评论) “” |