AOP是什么?
AOP(Aspect Orient Programming)是一种设计思想,是软件设计领域中的面向切面编程,它是面向编程(OOP)的一种补充和完善.它以通过预编译和运行期的代理方式,实现在不通过修改源码的情况下给程序动态添加额外功能的一种技术.如图-1所示:
AOP跟OOP区别
AOP跟OOP虽然说字面上差不多,但两种是不同领域的设计思想.OOP(面向对象)可以理解为一种静态过程(如一个系统分为几个模块,一个模块有哪些对象,对象有哪些属性),而AOP是一种动态过程,可以在对象运行时织入一些拓展功能或控制对象执行.
AOP应用场景
一般来说,我们会将一个系统分为核心业务和非核心业务,首先我们就要先实现核心业务,非核心业务是通过切入的方式添加到系统中,而这切入的方式就是AOP.
AOP就是要基于OCP(开闭原则),在不改变原有的核心功能情况下,额外的添加一下拓展功能并可以"控制"对象执行.例如AOP应用于项目中的日志处理,事务处理,权限处理,缓存处理等.如图-2所示
不用AOP如何基于OCP实现拓展功能?
答:手动通过继承或组合方式实现业务扩展
AOP应用分析
Spring AOP底层基于代理机制实现功能扩展:
①如果目标对象(被代理的对象)实现接口,则底层采用JDK动态代理机制为目标对象创建代理对象(目标类和代理类会实现共同接口),是用组合的方式实现.,那么需要在配置文件(applicatiion.properties)配置如下代码.
spring.aop.proxy-target-class=false.
②如果目标对象(被代理对象)没有实现接口,则底层可以采用CGLIB代理机制为目标对象创建代理对象(默认创建的代理类会继承目标对象类型),是用继承的方式实现,spring默认使用.
spring AOP原理分析如图-3所示:
AOP相关术语
切面(aspect):横切面对象,一般为一个具体类对象(可以借助@Aspect声明)
通知(Advice):在切面的某个特定的连接点上执行的动作(扩展功能),例如around,before,after等.
连接点(joinpoint):程序执行过程中某个特定的点,一般指被拦截到的方法.
切入点(pointcut):对多个连接点(Joinpoint)一种定义,一般可以理解为多个连接点的集合.
连接点与切入点定义如图-4所示:
说明:我们可以简单地将机场的一个安检口立即为连接点,多个安检口为切入点,安全检查过程看成是通知
spring AOP入门程序
添加日志
基于项目中的核心业务,添加简单的日志操作,借助SLF4J日志API输出目标方法的执行时长。(前提,不能修改目标方法代码)
添加依赖
在maven项目里的pom.xml添加AOP启动依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
基于此依赖spring可以整合AspectJ框架快速完成AOP的基本实现.Aspectj是一个面向切面的框架,它定义了AOP的一些语法,有一个专门的字节码生成器来生成遵守Java规范的class文件.
创建日志切面类对象
package com.cy.pj.common.aspect;
@Aspect
@Slf4j
@Component
public class SysLogAspect {
@Pointcut("bean(sysUserServiceImpl)")
public void logPointCut() {}
@Around("logPointCut()")
public Object around(ProceedingJoinPoint jp)
throws Throwable{
try {
log.info("start:"+System.currentTimeMillis());
Object result=jp.proceed();//调用下一个切面方法或目标方法
log.info("after:"+System.currentTimeMillis());
return result;
}catch(Throwable e) {
log.error(e.getMessage());
throw e;
}
}
}
说明:
此对象是给用户管理的业务(UserServiceImpl)添加日志
@Aspect 注解用于标识或者描述AOP中的切面类型,基于切面类型构建的对象用于为目标对象进行功能扩展或控制目标对象的执行.
@Pointcut注解用于描述切面中的方法,并定义切面中的切入点(基于特定表达式的方式进行描述),在本案例中切入点表达式用的是bean表达式,这个表达式以bean开头,bean括号中的内容为一个spring管理的某个bean对象的名字.
@Around注解用于描述切面中的方法,这样的方法被认为是一个环绕通知(核心业务方法执行之前和之后要执行的一个动作),@Around注解内部value属性的值为一个切入点表达式或者切入点表达式的一个引用(这个引用为一个@PointCut注解描述的方法的方法名).
业务切面测试实现
启动项目测试或进行单元测试,单元测试代码如下:
@SpringBootTest
public class AopTests {
@Autowired
private SysUserService userService;
@Test
public void testSysUserService() {
PageObject<SysUserDeptVo> po=
userService.findPageObjects("admin",1);
System.out.println("rowCount:"+po.getRowCount());
}
}
对于测试类中的userService对象而言,它有可能指向JDK代理,也有可能指向CGLIB代理,具体是什么类型的代理对象,要看application.yml配置文件中的配置(以上有说过其配置).
引用业务分析
在业务应用中,AOP相关的对象分析如图-5所示:
六大设计原则之开闭原则(OCP)(拓展)
OCP告诉我们,一个软件实体应该对修改关闭,对拓展开放.意思是说,当我们想改变软件时,应该在不修改源代码的情况下通过拓展代码功能来修改软件需求.开闭原则是最基础的原则,起到总指导的作用,其他原则(单一职责,里氏替换原则,依赖倒置,接口隔离,迪米特法则)都是开闭原则的具体形态,及其他原则都是开闭原则的手段和工具.
优点:提高复用性,可维护性,灵活性,易于测试
还想了解其他五大设计原则,请点这里