AOP(Aspect Oriented Programming) 面向切面编程
通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低.提高可重用性.
- 概念
- Joinpoint(连接点):就是业务层接口里面所有的方法,可以将连接业务层和动态代理增强后的方法连接起来.
- Pointcut(切入点):业务层里面被增强的方法 ,因为业务层接口不一定全部被增强了.
- Advice(通知/增强):拦截到连接点后要做的事.通知的类型有:前置通知,后置通知,异常通知,最终通知,环绕通知. 执行操作 有明确的切入点方法调用前后被分为 前置和后置通知. catch:异常通知 finally:最终通知 . 整个invoke方法在执行 就是环绕通知.
- Introduction (引介)
- Target(目标对象) :被代理对象.
- Weaving(织入): 把增强应用到目标对象来创建新的代理对象返回的过程. Spring采用动态代理织入.
- Proxy(代理) : 一个类被AOP织入增强后,就产生一个结果代理类.
- Aspect(切面):是切入点与通知的结合. (配置里面说明方法的参数,用通知说明方法的位置.)在配置文件中声明切入点与通知间的关系 即切面.
Spring基于XML的AOP
配置步骤
-
在bean.xml中导入官网的 xmlns:xsi 这段代码. (在pom.xml导入依赖 spring-context aspectjweaver[解析切入点表达式])
-
先配置Ioc
-
把通知Bean交给Spring来管理. (将通知Bean写入IOC)
-
使用aop:config标签表名开始AOP的配置.
-
在config里面 使用aop:aspect标签表明配置切面.
id属性 :给切面一个唯一标识. ref属性: 是指定通知类bean的Id.
在aop:aspect标签内部使用对应标签来配置通知的类型. 如:< aop:before> . 里面的的 method属性: 用于指定通知Bean中哪个方法是前置通知.pointcut属性:用于指定切入点表达式,该表达式的含义指的是对业务层中哪些方法增强.
切入点表达式的写法:
关键字:execution(表达式)
表达式 : 访问修饰符 返回值 包名.类名.方法名(参数列表)
如:pointcut=execution(public void com.hk.service.imp.AccountServiceImpl.saveAccount() )
当有多个通知时,切入点表达式一样, 可以写< aop:pointcut id="…" expression=" "> 然后通知用 pointcut-ref属性即可. 在切面标签内写 只能标签内用,标签外写所有的都可以用. 标签外 只能在切面之前出现.***全通配符写法更简单 *** `* *..*.*(..)` 1. 访问修饰符可省略 2. 返回值可以使用通配符 表示任意返回值. 3. 包名可以使用通配符 多级的表示 `*.*.*.*` 也可以使用 .. 表示当前包和子包. 4. 实际开发 表达式通常是切到业务层实现类下的所有方法.
- 环绕通知
问题:配置了环绕通知之后,切入点方法没有执行,而通知方法执行了.
答:因为该环绕通知中没有明确的切入点方法调用.
解决: 使用Spring框架提供的 ProceedingJoinPoint .该接口有一个方法porceed().此方法就相当于明确调用切入点方法.该接口可以作为环绕通知的方法参数,程序执行时,spring会为我们提供该接口的实现类供我们使用.Object args = pjp.getArgs(); pjp.proceed(args)
围绕pjo.proceed(args) 写各种通知. 写前面 就是前置通知…
环绕通知 : 是spring框架为我们提供的一种可以在代码中手动控制增强方法何时执行的方式.
注解AOP配置
- bean.xml 里面 加入 context约束.
- 配置spring创建容器时要扫描的包. < context:component-scan base-package="…">
- 配置spring开启注解AOP的支持 < aop-aspectj-autoproxy>< /aop-aspectj-autoproxy>
- 在业务层 加上@service
- 在切面 加上 @Component("…") 加入spring容器. @Aspect 表示当前是一个切面类
- @Pointcut(表达式) 表明要增强的业务方法
- 写通知 @相应的通知位置(表达式ID() ) 要加()
注解AOP配置 有通知的顺序问题. 单独写四个通知, 执行的顺序有问题. 自己写的环绕通知没问题.
不使用XML的配置方式 同新注解 只是在主配置类上还要加一个@EnableAspectJAutoProxy