spring aop

一.概念

​ aop 面向切面编程,可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。

​ 在一个业务流程中,需要在改业务流程开始前或执行后执行某些操作。然而这些操作与业务没有什么关系,而且所有类似业务都需要执行这样的操作,这是就需要在这些业务前后织入相应的代码。


二.AOP的优点

  • 实现程序功能模块的统一维护
  • 使业务逻辑之间耦合度降低,提高程序的可重用性
  • 提高程序的开发效率

三.AOP原理

​ 使用动态代理,对指定类的方法进行增强,生成增强的代理对象,使用父类引用指向该代理对象。


四.AOP术语

1.advice

​ 增强处理,把需要添加的功能先写好,等待织入。

2.JoinPoint

​ 连接点,就是被增强部分的增强代码织入点,例如方法前、方法后。

3.Pointcut

​ 切入点,例如在指定对象需要织入增强代码,但不是所有方法都需要增强,这些被增强的方法叫做切入点。

4.Aspect

​ 切面,切面就是切入点和增强代码的结合。

5.Introduction

​ 引入,允许我们向现有的对象添加新的方法属性。

6.Target

​ 引入中的现有对象,也就是需要被增强的对象,它可以再毫不知情的情况下,被织入增强代码。

7.Proxy

​ 代理,实现AOP,就是通过代理,生成增强的对象,外部持有该对象的引用。

8.Weaving

​ 织入,把切面织入到指定对象并生成代理对象的过程。


五.AOP原理

​ 通过Java的动态代理机制,把切点指定的类生成代理对象并代替原对象返回给Spring容器,用户在注入该对象时,会把该代理对象注入进去,从而得到了增强的代理对象。


六.Spring AOP的使用(注解方式)

[email protected]

​ 在类上使用,在该类中定义了切面和切点,也就是定义了对哪些对象增强,增强了什么功能。

[email protected]

​ 在方法上使用,定义了需要在哪些对象的哪些方法增强,同时定义了增强功能,并且在被增强方法执行前执行。

​ 示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
("execution(* com.test.*.dao.mapper..*.*(..))")
public void (JoinPoint joinPoint) throws Throwable {
MethodSignature methodSignature = (MethodSignature) (joinPoint.getSignature());
Method method = methodSignature.getMethod();


DataSource dataSource = method.getAnnotation(DataSource.class);
if (null != dataSource) {
JDBCContextHolder.setDataSourceType(dataSource.value());
} else {
JDBCContextHolder.setDataSourceType(DataSourceType.MASTER);
}
}

[email protected]

​ 在方法上使用,定义了需要在哪些对象的哪些方法增强,同时定义了增强功能,并且被增强方法返回后执行。

​ 示例:

1
2
3
4
5
@AfterReturning("execution(* com.test.*.dao.mapper..*.*(..))")
public void afterReturning(JoinPoint joinPoint) {
//清除数据源标记
JDBCContextHolder.clearDataSourceType();
}

[email protected]

​ AOP的AfterThrowing处理虽然可以对目标方法的异常进行处理,但这种处理与直接使用catch捕捉不同,catch捕捉意味着完全处理该异常,如果catch块中没有重新抛出新的异常,则该方法可能正常结束;而AfterThrowing处理虽然处理了该异常,但它不能完全处理异常,该异常依然会传播到上一级调用者,即JVM。

[email protected]

​ 后置通知, 在被增强方法执行之后执行 。

[email protected]

​ @Before 和@After的结合。


七.execution表达式

​ execution表达式的的作用是匹配相应的类或者方法。

​ 示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
任意公共方法的执行:
execution(public * *(..))

任何一个以“set”开始的方法的执行:
execution(* set*(..))

AccountService 接口的任意方法的执行:
execution(* com.xyz.service.AccountService.*(..))

定义在service包里的任意方法的执行:
execution(* com.xyz.service.*.*(..))

定义在service包或者子包里的任意方法的执行:
execution(* com.xyz.service..*.*(..))

在service包里的任意连接点(在Spring AOP中只是方法执行) :
within(com.xyz.service.*)

在service包或者子包里的任意连接点(在Spring AOP中只是方法执行) :
within(com.xyz.service..*)

实现了 AccountService 接口的代理对象的任意连接点(在Spring AOP中只是方法执行) :
this(com.xyz.service.AccountService)

八.AOP应用(工作中使用到的)

  • 结合自定义注解,实现动态切换数据源(读写分离)

  • spring事务

  • 异步任务