- AOP面向切面编程
Aop是一种编程思想,oop是面向对象编程,aop是面向切面编程,这两种思想不是互斥的,aop是oop的完善和补充,解决oop横向切面不足的能力。Oop在于对事物的抽象,aop在于对横向关注编程的能力,aop的作用是把开发中,业务代码和非业务代码分离重用。
实现方案:动态代理,spring支持两种动态代理,分别是JDK动态代理,CGlib动态代理。
AOP相关术语:
- 横切关注点:对那些方法进行拦截,拦截后怎么处理,这些关注点成之为横切关注点。
- 切面(aspect):类是对物体特征的抽象,切面就是对横切关注点的抽象。
- 连接点(jionpoint):程序执行时的某个特定的点,在spring中就是某一个方法的执行。
- 切入点(pointcut):对连接点进行拦截的定义。
- 通知(advice):所谓通知指的就是指拦截到连接点之后要执行的代码,通知分为前置,后置,异常,返回,环绕通知五类。
- 目标对象:代理的目标对象。
- 织入(weave):将切面应用到目标对象并导致代理对象创建的过程。
- 引入(introduction):在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段。
- Advisor(通知器):其实就是切点和通知的结合。
Spring Aop的实现
编写被代理类
//目标对象 实现的接口
public interface ICalcute {
public Integer add(Integer a,Integer b);
public Integer add(Integer a, Integer b ,Integer c);
public Integer div(Integer a,Integer b);
}
------------------------------------------------------------------------------------
//被代理类
@Component
public class SimpleCalcute implements ICalcute {
@Override
public Integer add(Integer a, Integer b) {
System.out.println("----add---run-----");
return a+b;
}
@Override
public Integer add(Integer a, Integer b ,Integer c) {
return a+b+c;
}
@Override
public Integer div(Integer a, Integer b) {
System.out.println("----div---run-----");
return a/b;
}
}
编写切面类
//切面类
/**
*1、切面类:对横向关注点的抽象
*2、@Aspect: 标记该类为切面
*3、@Component:标记为一个组件 注册到IOC容器
*/
@Aspect
@Component
public class LogAspect {
/**
* 1.切面中的方法为增强代码, 也就是通知。
* 2.增强代码执行时机: 目标方法执行前(前置通知)/ 返回数据(返回通知) / 执行后(后置通
知) /异常 (异常通知) ,
* 3. 特别的是环绕通知在上述几种情况下都执行。
* 4.异常通知和返回通知 互斥,原因是当出现异常 就不能获得返回值。
*/
@Before(value="execution( * com.bjlemon.aop.*.*(..) )")//前置通知
public void logInfo( JoinPoint jp> ) {
System.out.println("前置通知:增加日志功能....."+ jp.getSignature().getName()+"实参"+Arrays.toString(
jp.getArgs() ));
}
@After( value="execution( * com.bjlemon.aop.*.*(..) )" )//后置通知
public void logAfter() {
System.out.println("后置通知:保存到文件.....");
}
@AfterReturning(value="execution( * com.bjlemon.aop.*.*(..) )",returning="r")//返回通知
public void logReturn(JoinPoint jp, Object r ) {
System.out.println("返回通知拿到返回值"+r);
}
@AfterThrowing(value="execution( * com.bjlemon.aop.*.*(..) )",throwing="<u>ex</u>")//后置通知
public void logReturn(JoinPoint <u>jp</u>, Exception ex) {
System.out.println("异常通知:"+ex);
}
@Around(value="execution( * com.bjlemon.aop.*.*(..) )")//环绕通知
public void logArround( ProceedingJoinPoint p ) {
try {
System.out.println("前置通知");
Object obj= p.proceed( p.getArgs() );
// 目标方法执行
System.out.println("返回通知:"+obj);
} catch (Throwable e) {
System.out.println("异常通知");
}
System.out.println("后置通知");
}
}
XMl配置
<?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/springbeans.xsd http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
<!-- <u>ioc</u> 扫描包 -->
<context:component-scan base-package="com.bjlemon"/>
<!-- 开启动态代理 -->
<aop:aspectj-autoproxy/>
</beans>