Spring Aop 详解

1、AOP 简介
AOP(Aspect Oriented Programming),即面向切面编程,能够说是OOP(Object Oriented Programming,面向对象编程)的补充和完善。
OOP引入封装、继承、多态等概念来创建一种对象层次结构,用于模拟公共行为的一个集合。不过OOP只容许开发者定义纵向的关系,
但并不适合定义横向的关系,例如日志,事务,安全等。这些功能都是横向应用在业务处理中,而与它们对应的方法与其余代码基本没有联系,
如异常处理和透明的持续性也都是如此,不只增长了大量的代码量,还为程序后期的维护增生不少困难。
 
AOP技术偏偏相反,它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,
并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,
下降模块之间的耦合度,并有利于将来的可操做性和可维护性。
 
使用"横切"技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。
横切关注点的一个特色是,他们常常发生在核心关注点的多处,而各处基本类似,好比权限认证、日志、事物。AOP的做用在于分离系统中的各类关注点,
将核心关注点和横切关注点分离开来。
2、AOP 基本了解和通知方法
一、切面(Aspect):一个关注点的模块化,这个关注点可能会横切多个对象。事务管理是J2EE应用中一个关于横切关注点的很好的例子。
   在spring AOP中,切面可使用基于模式)或者基于Aspect注解方式来实现。通俗点说就是咱们加入的切面类(好比log类),能够这么理解。
二、链接点(Joinpoint):在程序执行过程当中某个特定的点,好比某方法调用的时候或者处理异常的时候。在Spring AOP中,
一个链接点老是表示一个方法的执行。通俗的说就是加入切点的那个点
三、通知(Advice):在切面的某个特定的链接点上执行的动做。其中包括了“around”、“before”和“after”等不一样类型的通知(通知的类型将在后面部分进行讨论)。许多AOP框架(包括Spring)都是以拦截器作通知模型,并维护一个以链接点为中心的拦截器链。
四、切入点(Pointcut):匹配链接点的断言。通知和一个切入点表达式关联,并在知足这个切入点的链接点上运行(例如,当执行某个特定名称的方法时)。
切入点表达式如何和链接点匹配是AOP的核心:Spring缺省使用AspectJ切入点语法。
五、引入(Introduction):用来给一个类型声明额外的方法或属性(也被称为链接类型声明(inter-type declaration))。
Spring容许引入新的接口(以及一个对应的实现)到任何被代理的对象。例如,你可使用引入来使一个bean实现IsModified接口,以便简化缓存机制。
六、目标对象(Target Object): 被一个或者多个切面所通知的对象。也被称作被通知(advised)对象。 既然Spring AOP是经过运行时代理实现的,
这个对象永远是一个被代理(proxied)对象。
七、AOP代理(AOP Proxy):AOP框架建立的对象,用来实现切面契约(例如通知方法执行等等)。在Spring中,AOP代理能够是JDK动态代理或者CGLIB代理。
八、织入(Weaving):把切面链接到其它的应用程序类型或者对象上,并建立一个被通知的对象。这些能够在编译时(例如使用AspectJ编译器),
类加载时和运行时完成。Spring和其余纯Java AOP框架同样,在运行时完成织入。
通知方法:
1.前置通知(Before advice):在某链接点以前执行的通知,但这个通知不能阻止链接点以前的执行流程(除非它抛出一个异常)。
2.后置通知(After returning advice):在某链接点正常完成后执行的通知:例如,一个方法没有抛出任何异常,正常返回。
3.异常通知(After throwing advice):在方法抛出异常退出时执行的通知。
4.最终通知(After (finally) advice):当某链接点退出的时候执行的通知(不管是正常返回仍是异常退出)。
5.环绕通知(Around Advice):包围一个链接点的通知,如方法调用。这是最强大的一种通知类型。环绕通知能够在方法调用先后完成自定义的行为。
 它也会选择是否继续执行链接点或直接返回它本身的返回值或抛出异常来结束执行。
 
3、Spring对AOP的支持
Spring中AOP代理由Spring的IOC容器负责生成,管理,它的依赖关系也有IOC容器负责。所以,AOP代理能够直接使用容器中的其余bean示例做为目标,
这种关系可由IOC容器的依赖注入提供(不熟悉依赖注入的能够看看我以前的博文)。Spring建立代理规则为:
一、默认使用JDK动态代理来建立AOP代理,这样能够为任何接口示例建立代理
二、当须要代理的类不是代理接口时,Spring会切换为使用CGLIB代理,也可强制使用CGLIB代理。(强制方法:在XML配置中修改 AOP 属性
spring.aop.proxy-target-class=true或在注释中修改@EnableAspectJAutoProxy(proxyTargetClass = true)
进行AOP编程的关键就是定义切入点和定义加强处理,一旦定义了合适的切入点和加强处理,AOP框架将自动生成AOP代理,
即:代理对象的方法=加强处理+被代理对象的方法
 
4、Spring AOP 栗子
一、定义一个接口
package com.samter.common;
public interface car {
void run(String name);
}
二、接口的实现类
package com.samter.commonImpl;
public class carImpl implements car{
 
public void run(String name) {  
System.out.println("【一辆】"+name+"正在飙车...");  
}  
 
}
三、切面
package com.samter.aspect;
import org.aspectj.lang.annotation.AfterReturning;  
import org.aspectj.lang.annotation.Aspect;  
import org.aspectj.lang.annotation.Before;  
import org.aspectj.lang.annotation.Pointcut;  
@Aspect  
public class Aspects {  
 
//  第一个*表明任意返回值类型 后面的表示扫描com.samter下的全部包
//  包下的全部类,类里面的全部方法,方法的全部参数
@Pointcut("execution(* com.samter.*.*.*(..))")  
public void foundCar() {}  
 
@Before(value="foundCar()")  
public void foundBefore() {  
System.out.println("【交警】发现一辆车正在飙车...");  
}  
 
@AfterReturning("foundCar() && args(name,..)")  
public void foundAfter(String name) {  
System.out.println("【交警】拦下车,车名是“"+name+"”...");  
}  
@AfterReturning("foundCar()")
public void foundAfter() {
System.out.println("【交警】开罚单");
}
 
}
四、XML配置
 

 

 
五、测试
package com;
 
import org.springframework.context.ApplicationContext;  
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
import com.samter.common.Pig;
import com.samter.common.commo.Dog;  
 
public class Main {  
 
 public static void main(String[] args) {  
 ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");  
 
 
 Car car  = (Car) context.getBean("car");
 
 car.run(“宝马”);
 }  
 
}
六、结果
【交警】发现一辆车正在飙车...
一辆宝马正在飙车...
【交警】拦下车,车名是宝马...
【交警】开罚单
七、后置
1.运行前别忘记导 jar 包(没有去网上下)
2.运行错误时查看是否是类名写错了或者是XML文件没有读取到,XML放在根路径下
3.写测试类是注意不要导错文件包
八、后记
这里只写了前置通知和后置通知,其余通知除环绕通知外用法都差很少,环绕通知你们能够去百度下,
网上许多大神都有详细的栗子。
5、图片