AOP(Aspect Oriented Programming),即面向切面编程,利用一种称为"横切"的技术,剖开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。
连接点(Joinpoint):连接点是程序类中客观存在的方法,可被Spring拦截并切入内容。
切入点(Pointcut):被Spring切入连接点。
通知、增强(Advice):可以为切入点添加额外功能,分为:前置通知、后置通知 返回通知、异常通知、环绕通知。
目标对象(Target):代理的目标对象
引介(Introduction):一种特殊的增强,可在运行期为类动态添加Field和Method。
织入(Weaving):把通知应用到具体的类,进而创建新的代理类的过程。
代理(Proxy):被AOP织入通知后,产生的结果类。
切面(Aspect):由切点和通知组成,将横切逻辑织入切面所指定的连接点中。
AOP依赖
- <dependency>
- <groupId>org.springframeworkgroupId>
- <artifactId>spring-aspectsartifactId>
- <version>5.1.6.RELEASEversion>
- dependency>
spring-context.xml引入AOP命名空间
- "1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="
- http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans.xsd
- http://www.springframework.org/schema/aop
- http://www.springframework.org/schema/aop/spring-aop.xsd
- ">
- beans>
在写
AOP无入侵,能在不修改源代码的情况加插入一些辅助功能/非核心业务功能
aop作用:Spring的AOP编程即是通过动态代理类为原始类的方法添加辅助功能。
定义原始类


定义通知类增加额外功能

定义bean标签

定义切入点(PointCut)

上图必须写UserService.add() 描述了增强的位置,增强那个方法。
测试

上图ac.getBean(UserService.class),可以直接返回UserSercvice对象,不用强转了。


也可以写*(),表示UserService里的所有空参方法,在测试类里直接改法,service.add()、service.update()、等等,如果是有参构造,写

两个参数

有没有参数都行 add(..)
返回值是 void Integer String等等
![]()
service下的所有方法
包及子包

- public class UserServiceImpl implements UserService {
- @Override
- public void add() {
- System.out.println("add............");
- }
-
- @Override
- public void delete() {
- System.out.println("delete..........");
- // int i =1/0;
- }
-
- @Override
- public void update() {
-
- System.out.println("update................");
-
- }
-
- @Override
- public int query() {
- System.out.println("query.............");
- int i =1/0;
- return 1;
- }
-
- @Override
- public void getAll() {
- System.out.println("getAll.............");
- }
- }
- public class MyAspect {
- public void before(){
- System.out.println("前置通知执行了");
- }
-
- public void bbbb(){
- System.out.println("后置通知执行了");
- }
-
- public void afterReturning(){
- System.out.println("返回通知执行了");
- }
-
- public void afterThrowing(){
- System.out.println("目标方法出错了 我来救场...");
- }
-
- public void around(ProceedingJoinPoint pjp){
- System.out.println("start:" + System.currentTimeMillis());
- try {
- pjp.proceed();
- } catch (Throwable throwable) {
- throwable.printStackTrace();
- }
- System.out.println("end:" + System.currentTimeMillis());
-
-
- }
-
- }

上图也可以进行前置通知方法


前置:在切点方法之前执行。
后置:在切点方法之后执行。
返回通知:有异常不执行。
异常通知:有异常才执行 。
环绕通知:在切点方法前后 模拟一次切点方法执行 可以在方法前后记录方法执行时间。