一,什么是AOP
(1)面向切面编程(方面),利用AOP可以对业务逻辑的各个部分进行隔离,从而是的业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
(2)通俗描述:不通过修改源代码方式,在主干功能里面添加新功能
(3)使用登录的例子说明AOP
二,AOP的概念
面向切片编程(AOP—Aspect Oriented Programming)可以说是对OOP(面向对象编程)的补充和完善,面向对象就是将事物的特性和行为抽象为一个对象,如people类有身高、体重、年龄等属性,也有吃饭、睡觉等行为。把这些特性和行为封装成一个类,然后可以统一调用。面向切片也可以举个例子,比如people类有自己的属性和行为,但是有小一部分人生病要去医院看病,看病这个业务逻辑就不属于哪一个类,因为people泛指所有人,所有人不会都看病。AOP就是把医院看病这一个业务逻辑功能抽取出来,然后动态把这个功能切入到需要的方法(或行为)中,需要的才切入,这样便于减少系统的重复代码,降低模块间的耦合度。常用到AOP的就是安全校验、日志操作、事务操作等,给你先定义好,然后在想用的地方用,这样不会影响已经在服务器运行的项目,然后又能注入新功能,灵活。我们开发dao->service->controller是纵向的,这个AOP就是横向切入,如横向切入一个日志Log,打印执行过程。
Spring AOP就是基于动态代理实现的, 分为两种代理,jdk动态代理(基于接口)和cglib代理(基于类的)。如果目标对象实现了接口,就用jdk动态代理,如果未实现接口就用cglib动态代理。虽然动态代理可以解决耦合问题,但比较抽象,复杂,属于底层实现代理模式,我们这里直接用AOP,AOP做了很多封装,只要调用API即可,简化开发,但是AOP底层原理还是需要了解。
注意:动态代理底层利用了反射机制,反射包下Proxy类,如果想了解底层原理的,推荐这个视频 动态代理详解。
Aspect(切面): Aspect 声明类似于 Java 中的类声明,在 Aspect 中会包含着一些 Pointcut 以及相应的 Advice。
Joint point(连接点):表示在程序中明确定义的点,典型的包括方法调用,对类成员的访问以及异常处理程序块的执行等等,它自身还可以嵌套其它 joint point。
Pointcut(切点):表示一组 joint point,这些 joint point 或是通过逻辑关系组合起来,或是通过通配、正则表达式等方式集中起来,它定义了相应的 Advice 将要发生的地方。
Advice(增强):Advice 定义了在 Pointcut 里面定义的程序点具体要做的操作,它通过 before、after 和 around 来区别是在每个 joint point 之前、之后还是代替执行的代码。
Target(目标对象):织入 Advice 的目标对象.。
Weaving(织入):将 Aspect 和其他对象连接起来, 并创建 Adviced object 的过程
三,AOP的作用
提供声明式事务;允许用户自定义切面
主要内容: 接口、实现类、核心类、配置类、测试类
创建接口
public interface BookService {
void findAll();
void save(int a);
int del();
void update();
}
实现类
public class BookServiceImpl implements BookService {
public void findAll(){
System.out.println("查找所有信息");
}
public void save(int a){
System.out.println("保存信息+a");
}
public int del(){
System.out.println("删除信息");
return 0;
}
public void update(){
System.out.println("修改信息");
}
}
核心类
public class Logger {
public void check(){System.out.println("前置通知/增强;权限验证");}
public void logPrint(){System.out.println("后置通知/增强;日志输出");}
public void exception(){System.out.println("异常通知/增强;异常处理");}
public void distroy(){System.out.println("最终通知/增强;资源释放");}
}
配置类
<?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/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--1.把所有类的对象交给IOC容器进行管理-->
<bean id="logger" class="com.gao.logger.Logger" />
<bean id="bookService" class="com.gao.service.impl.BookServiceImpl" />
<!--2.AOP的配置:让增强类 的 哪个方法 动态进行何种增强 核心类 的 哪个方法-->
<aop:config>
<!--指定增强类并起个名字-->
<aop:aspect id="check" ref="logger">
<!--前置通知/增强:在核心类方法执行之前 进行 增强-->
<aop:before method="check" pointcut="execution(* *..BookServiceImpl.*(..))" />
<aop:after-returning method="logPrint" pointcut="execution(* *..BookServiceImpl.*(..))" />
<aop:after-throwing method="exception" pointcut="execution(* *..BookServiceImpl.*(..))" />
<aop:after method="distroy" pointcut="execution(* *..BookServiceImpl.*(..))" />
</aop:aspect>
</aop:config>
</beans>
测试类
public class Test01 {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
BookService bookService = context.getBean(BookService.class);
bookService.findAll();
bookService.save(5);
bookService.del();
bookService.update();
}
}
运行结果: