AOP通过提供程序设计的另一种思路扩展了OOP,OOP的核心元素是class,而AOP的核心是Aspect。Aspect使得关注点模块化。AOP是spring的核心模块。虽然LOC容器不依赖AOP,但AOP通过提供非常有效的中间件解决方案扩展了IOC容器。Spring2.0引入了 @AspectJ样式(更简洁、有效的书写自定义Aspect)
5.1 AOP概念
这些概念不是spring的特性。方面(Aspect):一个关注点的模块化,这个关注点实现可能另外横切多个对象。Aspect用spring的 Advisor或拦截器实现。连接点(Joinpoint): 程序执行过程中明确的点,如方法调用或特定的异常被抛出。通知(Advice): 在特定连接点AOP框架执行的动作。许多AOP框架包括Spring都是以拦截器做通知模型,维护一个“围绕”连接点的拦截器链。Spring中定义了四个advice: BeforeAdvice, AfterAdvice, ThrowAdvice和DynamicIntroductionAdvice切点(Pointcut): 指定一个通知将被引发的一系列连接点的集合。AOP框架必须允许开发者指定切点:例如,使用正则表达式。 Spring定义了Pointcut接口,用来组合MethodMatcher和ClassFilter,可以通过名字很清楚的理解, MethodMatcher是用来检查目标类的方法是否可以被应用此通知,而ClassFilter是用来检查Pointcut是否应该应用到目标类上AOP代理(AOP Proxy): AOP框架创建的对象。 在Spring中AOP代理可以是JDK动态代理或CGLIB代理。织入(Weaving): 组装Aspect来创建一个被通知对象。这可以在编译时完成(例如使用AspectJ编译器),也可以在运行时完成。Spring和其他纯JavaAOP框架一样,在运行时完成织入。spring中advice的typeBefore(BeforeAdvice):在连接点之前运行,但不可阻止执行流到达连接点(触发它本身抛出异常)After returning:在连接点完成后执行(比如方法正常返回时)After throwing:方法抛异常时执行After (finally):不管连接点是否正常退出,都会执行Around:环绕,可以再方法触发前后实现自定义行为,也可以决定是否要执行连接点或者返回自己的返回值(以及异常)来提前中断连接点执行。Around是最强大的advice类型,spring建议使用可以达到目的的最小效能类型。举个栗子,如果需要更新方法返回值的缓存,最好使用After而不是Around,尽管后者也能达到目的。使用更简化的type能提供更简洁的编程模型,降低出错概率。AOP的核心概念是切点匹配连接点,这区别于老式的消息监听策略。切点使得advice能够在独立于面向对象层级下被命中。
5.2 Spring AOP 的特性和目标
纯JAVA实现,不需要控制类加载层级,因此适合在servlet容器和应用server中应用。Spring AOP仅支持方法级别的连接点。字段级别不支持,如果需要可以使用AspectJ。与大多数AOP框架不同,Spring AOP的目标不是完全的实现AOP,而是将AOP实现与AOP容器更有效的集成起来。Spring AOP从不想与AspectJ竞争,Spring确信任何基于代理的框架都可以相互补充而不是竞争。Spring通过AspectJ将Spring AOP和IOC容器无缝集成起来,是的所有AOP的应用都可以在spring应用架构内。Spring框架的一个信条就是无侵入性,也就说使用者不应被强制引入框架内的类和接口(在业务逻辑中)。5.3 AOP代理
Spring AOP默认使用标准JDK动态代理,可以代理所有的接口。也可以使用CGLIB代理,CGLIB可以代理非接口实现的业务对象。一般建议使用基于接口的编程。5.4 @AspectJ
该注解使得AspectJ语言可以使用。5.4.1 @AspectJ支持
为了在spring中使用@AspectJ aspects,需要need to enable Spring support for configuring Spring AOP based on @AspectJ aspects and auto-proxying beans based on whether or not they are advised by those aspects.通过自动代理,如果spring确定一个bean要被一个或多个aspects通知,它就会为这个bean自动生成一个代理来拦截方法调用,以确保通知被按需执行。@Configuration@EnableAspectJAutoProxy //使得@AspectJ支持java的@Configurationpublic class AppConfig {}