Web框架-Spring-SpringAOP
Spring的核心是什么
Spring核心内容:IOC
和AOP
。IoC (Inversion of Control,控制反转)
和 AOP(Aspect Oriented Programming,面向切面编程)
。
AOP
什么是AOP?为什么需要AOP
AOP(Aspect Orient Programming)也就是面向切面编程,作为面向对象编程的一种补充,它允许开发人员在不改变原来模型的基础上动态的去修改模型用来满足新的需求。
AOP专门用于处理系统中分布于各个模块(不同方法)中的交叉关注点的问题(一个程序中跨越多个点的功能被称为横切关注点,这些横切关注点在概念上独立于应用程序的业务逻辑。),在JavaEE应用中,常常通过AOP来处理一些具有横切性质的系统级服务,如事务管理、安全检查、缓存、对象池管理、日志记录等,AOP已经成为一种非常常用的解决方案。
在 OOP 中模块化的关键单元是类,而在 AOP 中模块化的关键单元是方面。AOP 帮助你将横切关注点从它们所影响的对象中分离出来,然而依赖注入帮助你将你的应用程序对象从彼此中分离出来。
Spring 框架的 AOP 模块提供了面向方面的程序设计实现,允许你定义拦截器方法和切入点,可以实现将应该被分开的代码干净的分开功能。
AOP涉及名称:
切面(Aspect):其实就是共有功能的实现。如日志切面、权限切面、事务切面等。在实际应用中通常是一个存放共有功能实现的普通Java类,之所以能被AOP容器识别成切面,是在配置中指定的。
通知(Advice):是切面的具体实现。以目标方法为参照点,根据放置的地方不同,可分为前置通知(Before)、后置通知(AfterReturning)、异常通知(AfterThrowing)、最终通知(After)与环绕通知(Around)5种。在实际应用中通常是切面类中的一个方法,具体属于哪类通知,同样是在配置中指定的。
连接点(Joinpoint):就是程序在运行过程中能够插入切面的地点。例如,方法调用、异常抛出或字段修改等,但 Spring只支持方法级的连接点。
切入点(Pointcut):用于定义通知应该切入到哪些连接点上。不同的通知通常需要切入到不同的连接点上,这种精准的匹配是由切入点的正则表达式来定义的。
目标对象(Target):就是那些即将切入切面的对象,也就是那些被通知的对象。这些对象中已经只剩下干干净净的核心业务逻辑代码了,所有的共有功能代码等待AOP容器的切入。
代理对象(Proxy):将通知应用到目标对象之后被动态创建的对象。可以简单地理解为,代理对象的功能等于目标对象的核心业务逻辑功能加上共有功能。代理对象对于使用者而言是透明的,是程序运行过程中的产物。
织入(Weaving):将切面应用到目标对象从而创建一个新的代理对象的过程。这个过程可以发生在编译期、类装载期及运行期,当然不同的发生点有着不同的前提条件。譬如发生在编译期的话,就要求有一个支持这种AOP实现的特殊编译器;发生在类装载期,就要求有一个支持AOP实现的特殊类装载器;只有发生在运行期,则可直接通过Java语言的反射机制与动态代理机制来动态实现。
使用AspectJ实现AOP
AspectJ是一个基于Java语言的AOP框架,提供了强大的AOP功能,其他很多AOP框架都借鉴或采纳其中的一些思想。
其主要包括两个部分:一个部分定义了如何表达、定义AOP编程中的语法规范,通过这套语法规范,可以方便地用AOP来解决Java语言中存在的交叉关注点的问题;另一个部分是工具部分,包括编译、调试工具等。
AOP实现可分为两类:
静态AOP实现: AOP框架在编译阶段对程序进行修改,即实现对目标类的增强,生成静态的AOP代理类,以AspectJ为代表;
动态AOP实现: AOP框架在运行阶段动态生成AOP代理,以实现对目标对象的增强,以 Spring AOP为代表。
一般来说,静态AOP实现具有较好的性能,但需要使用特殊的编译器。动态AOP实现是纯Java实现,因此无须特殊的编译器,但是通常性能略差。
Spring的AOP支持
Spring中的AOP代理由 Spring的IoC
容器负责生成、管理,其依赖关系也由IoC
容器负责管理。
为了在应用中使用@AspectJ支持, Spring需要添加三个库:
aspectjweaver.jar
aspectjrt.jar
aopalliance.jar
并在 Spring配置文件中做如下配置:
<!--启动@AspectJ支持-->
<aop:aspectj-autoproxy/>
<!--指定自动搜索Bean组件、自动搜索切面类-->
<context:component-scan base-package="edu.shu.sprint.service">
<context:include-filter type="annotation" expression="org.aspectj.lang.annotation.Aspect"/>
</context:component-scan>