Spring AOP 基础

in java with 0 comment

概念

AOP Aspect Oritened Programming 被称为面向切面编程。

OOP Object Oritened Programming 被称为面向对象编程。

面向对象编程侧重点为对象;面向切面编程侧重点为切面。

在大量组件中寻找时间、地点、逻辑相同的层面。比如Dao所有方法前开启事务、Controller所有方法后xxxx。

面向切面编程是以面向对象编程为基础,考虑将共通业务处理进行隔离,独立封装,之后通过SpringAOP配置方式作用。

AOP优点:将传统业务和共通业务代码进行解耦。例如事务控制、权限控制、日志记录等。

1. 切面组件(Aspect Bean)

封装共通处理的组件,将来会通过配置动态作用到其他业务组件方法上的功能。(要追加什么功能?)

2. 切入点(pointcut)

用于指定哪些业务组件方法追加切面组件功能。Spring提供了多种切入点表达式,例如方法表达式、类型表达式、组件名称表达式等。(给谁加功能?)

execution(修饰符? 返回类型 方法名(参数) 抛出异常?)

	//匹配容器中所有bean中find开头的方法
	execution(* find*(..))

	//匹配DeptSerive组件中find开头的方法
	execution(* cn.xdl.service.DeptSerive.find*(..))

	//匹配cn.xdl.service包中所有类所有方法
	execution(* cn.xdl.service.*.*(..))

	//匹配cn.xdl.service包及子包中所有类所有方法
	execution(* cn.xdl.service..*.*(..))

within(包名.类名)

	//匹配DeptService组件所有方法
	within(cn.xdl.service.DeptService)

	//匹配cn.xdl.service包中所有类所有方法
	within(cn.xdl.service.*)

	//匹配cn.xdl.service包及子包中所有类所有方法
	within(cn.xdl.service..*)
bean(bean名字)

	//匹配id=deptService的bean对象的所有方法
	bean(deptService)

	//匹配id以Service结尾的bean对象所有方法
	bean(*Service)
  1. 通知(Advice)
用于指定业务组件和切面组件作用的时机。例如业务组件方法前、方法后、异常发生后等类型。(什么时候加?)

Spring框架提供以下几种通知:

- 前置通知  : 在目标方法前加切面功能
- 后置通知  : 在目标方法后加切面功能(目标方法正常结束)
- 最终通知  : 在目标方法后加切面功能(目标方法正常或不正常结束)
- 异常通知  : 在目标方法抛出异常后加切面功能
- 环绕通知  : 在目标方法前和后加切面功能
- 其他封装后的通知(例如事务等)


try{
	//前置通知执行时机
	//执行目标方法
	//后置通知执行时机
}catch(){
	//异常通知执行时机
}finally{
	//最终通知执行时机
}

不同类型通知,对应切面组件的方法定义格式:
	public void xxx(); //前置
	public void xxx(参数); //后置
	public void xxx(); //最终
	public void xxx(Exception ex);//异常
	public Object xxx(PrceedingJoinPoint pjp);//环绕

4. 目标组件(Target)

要被追加切面组件功能的组件。即:切入点指定的组件。

5. 动态代理(AutoProxy)

Spring AOP实现原理是采用动态代理技术完成的。Spring框架提供了两种生成代理对象的技术,分别是JDK Proxy API和CGLIB技术。

默认情况下有接口的目标组件采用JDK Proxy生成;没有接口的会采用CGLIB技术生成。

CGLIB技术原理:根据现有组件动态创建一个子类组件,然后将父类所有方法进行重写,在重写方法时可以调用父类功能和切面追加功能。

public class EmpServiceImpl$$EnhancerBySpringCGLIB$$55949fc7 extends EmpServiceImpl{
	public void add() {
		super.add();//调用父类add方法
		loggerBean.mylog();//调用切面功能
	}

	public void findAll() {
		super.findAll();//调用父类findAll方法
		loggerBean.mylog();//调用切面功能
	}
}

JDK Proxy API技术原理:根据现有组件接口动态创建一个代理组件。然后将接口方法进行实现,在方法中可以调用父类功能和切面追加功能。

public class $Proxy6 implements DeptService{
	public void add() {
		DeptServiceImpl.add();//调用组件方法
		loggerBean.mylog();//调用切面功能
	}
}

提示:可以在aop配置时,强制指定cglib技术生成子类代理对象。

<aop:config proxy-target-class="true">