`
Feiing
  • 浏览: 240374 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Spring AOP 概览与细节

阅读更多
    
   @王政 @2007-08-04 @转载请注明出处

   在这个追求速度与效率的时代,   AOP 已经成为企业应用开发重要的手段,  而 Spring AOP 无疑是其主流,  本文将从  AOP alliance 开始对 spring aop 做一个简单的概括,  同时也会对其中的重要细节做一些说明.  由于笔者对 spring2.0 尚未做过多了解, 本文将延续 spring1.0 风格.

主题一 : AOP 核心概念

   首先来看 spring reference 对 aop 核心概念的描述 :
  
spring reference 写道

   6.1.1. AOP concepts

Let us begin by defining some central AOP concepts. These terms are not Spring-specific. Unfortunately, AOP terminology is not particularly intuitive. However, it would be even more confusing if Spring used its own terminology.

    * Aspect: A modularization of a concern for which the implementation might otherwise cut across multiple objects. Transaction management is a good example  of a crosscutting concern in J2EE applications. Aspects are implemented using Spring as Advisors or interceptors.
   
    * Joinpoint: Point during the execution of a program, such as a method invocation or a particular exception being thrown. In Spring AOP, a joinpoint is always method invocation. Spring does not use the term joinpoint prominently; joinpoint information is accessible through methods on the MethodInvocation argument passed to interceptors, and is evaluated by implementations of the org.springframework.aop.Pointcut interface.
   
    * Advice: Action taken by the AOP framework at a particular joinpoint. Different types of advice include "around," "before" and "throws" advice. Advice types are discussed below. Many AOP frameworks, including Spring, model an advice as an interceptor, maintaining a chain of interceptors "around" the joinpoint.
   
    * Pointcut: A set of joinpoints specifying when an advice should fire. An AOP framework must allow developers to specify pointcuts: for example, using regular expressions.
   
    * Introduction: Adding methods or fields to an advised class. Spring allows you to introduce new interfaces to any advised object. For example, you could use an introduction to make any object implement an IsModified interface, to simplify caching.
   
    * Target object: Object containing the joinpoint. Also referred to as advised or proxied object.
   
    * AOP proxy: Object created by the AOP framework, including advice. In Spring, an AOP proxy will be a JDK dynamic proxy or a CGLIB proxy.
   
    * Weaving: Assembling aspects to create an advised object. This can be done at compile time (using the AspectJ compiler, for example), or at runtime. Spring, like other pure Java AOP frameworks, performs weaving at runtime.

Different advice types include:

    * Around advice: Advice that surrounds a joinpoint such as a method invocation. This is the most powerful kind of advice. Around advices will perform custom behavior before and after the method invocation. They are responsible for choosing whether to proceed to the joinpoint or to shortcut executing by returning their own return value or throwing an exception.
   
    * Before advice: Advice that executes before a joinpoint, but which does not have the ability to prevent execution flow proceeding to the joinpoint (unless it throws an exception).
   
    * Throws advice: Advice to be executed if a method throws an exception. Spring provides strongly typed throws advice, so you can write code that catches the exception (and subclasses) you're interested in, without needing to cast from Throwable or Exception.
   
    * After returning advice: Advice to be executed after a joinpoint completes normally: for example, if a method returns without throwing an exception.

Around advice is the most general kind of advice. Most interception-based AOP frameworks, such as Nanning Aspects, provide only around advice.

As Spring, like AspectJ, provides a full range of advice types, we recommend that you use the least powerful advice type that can implement the required behavior. For example, if you need only to update a cache with the return value of a method, you are better off implementing an after returning advice than an around advice, although an around advice can accomplish the same thing. Using the most specific advice type provides a simpler programming model with less potential for errors. For example, you don't need to invoke the proceed() method on the MethodInvocation used for around advice, and hence can't fail to invoke it.

The pointcut concept is the key to AOP, distinguishing AOP from older technologies offering interception. Pointcuts enable advice to be targeted independently of the OO hierarchy. For example, an around advice providing declarative transaction management can be applied to a set of methods spanning multiple objects. Thus pointcuts provide the structural element of AOP.
  


下图也许能更直观表述这些概念


从图中可以看出, aop alliance 定义了 Advice, JointPoint 两个核心 interface, Pointcut 接口是在 spring 中定义的, 最常用的 MethodInterceptor 是 Advice 的 sub interface, 下面简单列一下 aop alliance 各核心接口及其作用

1. Advice :  Tag interface for Advice. Implementations can be any type of advice, such as Interceptors.

2. Interceptor : This interface represents a generic interceptor.

A generic interceptor can intercept runtime events that occur within a base program.

Those events are materialized by (reified in) joinpoints.

Runtime joinpoints can be invocations, field access, exceptions...

Intercetpor 的三个 sub interface :

3. ConstructorInterceptor, FieldInterceptor, MethodInterceptor
   从名字看已经很直白, 分别用于拦截对象构建, 属性访问, 方法调用,
   对应的 JoinPoint 分别为 ConstructorInvocation, FieldAccess, MethodInvocation,
   其中 spring 只支持 MethodInterceptor
  
4. Joinpoint :  This interface represents a generic runtime joinpoint (in the AOP terminology).

A runtime joinpoint is an event that occurs on a static joinpoint (i.e. a location in a the program). For instance, an invocation is the runtime joinpoint on a method (static joinpoint).

The static part of a given joinpoint can be generically retrieved using the getStaticPart() method.

In the context of an interception framework, a runtime joinpoint is then the reification of an access to an accessible object (a method, a constructor, a field), i.e. the static part of the joinpoint. It is passed to the interceptors that are installed on the static joinpoint.

Joinpoint 的三个 sub interface :
5. ConstructorInvocation, FieldAccess, MethodInvocation
   也很直白, 同时对应 3 可以知道, spring 只支持 MethodInvocation
  
aop alliance 定义的接口应该被 aop container 实现, 比如 nanning aop, spring 等

再来看 spring 对 aop alliance 的实现和增强

1. Pointcut : Core Spring pointcut abstraction.
    
A pointcut is composed of a ClassFilter and a MethodMatcher.
Both these basic terms and a Pointcut itself can be combined to build up combinations  (e.g. through org.springframework.aop.support.ComposablePointcut).
             
   笔者注 : 很奇怪 Pointcut 为什么没有出现在 aop alliance 接口定义里, 可能是为了让实现有更多的选择 ?
  
   Pointcut 就是传说中的 "切入点" 了, spring 的主要实现包括 StaticMethodMatcherPointcut, DynamicMethodMatcherPointcut 以及 AspectJExpressionPointcut, DynamicMethodMatcherPointcut 因为性能问题使用率不高, AspectJExpressionPointcut 是 spring2.0 才引入的, 本文不再讲述,StaticMethodMatcherPointcut 中最常用的是基于正则表达式的实现 JdkRegexpMethodPointcut 和 Perl5RegexpMethodPointcut,  前者需要 JDK1.4+ 的环境, 后者需要 Jakarta ORO lib, 一个典型的配置
  
<bean id="settersPointcut" class="org.springframework.aop.support.Perl5RegexpMethodPointcut">
	    <property name="patterns">
	        <list>
	            <value>.*set.*</value>
	        </list>
	    </property>
</bean>

  
   上述配置匹配所有的 set 方法, 而
  
   
<bean id="settersPointcut" class="org.springframework.aop.support.Perl5RegexpMethodPointcut">
		    <property name="patterns">
		        <list>
		            <value>com.mycom.Foo.*set.*</value>
		        </list>
		    </property>
</bean>

  
   仅匹配 com.mycom.Foo 中的所有 set 方法
  
2. MethodInterceptor, BeforeAdvice, ThrowsAdvice, AfterReturningAdvice,   IntroductionAdvice

   MethodInterceptor : 最常用的 advice, 大家最熟悉的 TransactionInterceptor 就是其实现,
   需要注意的地方是实现中一定要调用 invocation.proceed() 使 interceptor chain 继续执行
  
   BeforeAdvice : 不再赘述了, reference 中写的很明白
  
   ThrowsAdvice : 我认为非常有用的 advice, 强大的地方在于它只是一个标志接口, 实现可以选择需要拦截的 Throwable 类型, 当然也可以获取 MethodInvocation 中的一切信息, ThrowsAdvice 可以实现非常完善的 exception handle 机制
  
   AfterReturningAdvice : 使用率不高, 不再赘述
  
   IntroductionAdvice : 另一个非常强大的 advice, 限于文章篇幅, 也不再细数了, 使用它可以实现一些很眩的功能
  
3. Advisor :  Base interface holding AOP advice (action to take at a joinpoint)
   and a filter determining the applicability of the advice
   (such as a pointcut).
  
   This interface is not for use by Spring users, but to allow for commonality      in support for different types of advice.

Spring AOP is based around around advice delivered via method interception,
compliant with the AOP Alliance interception API.

The Advisor interface allows support for different types of advice,
such as before and after advice, which need not be implemented using interception.

  
   Advisor hold 了 Advice, 并且决定 advice 是否执行, 比如最常用的 PointcutAdvisor, 它包含了 getPointcut() 方法,
  通俗的讲, Advice 是 "做什么 ", Pointcut 是 "何时做", 而 PointcutAdvisor 是 "何时做, 做什么",
   配合下文提到的 DefaultAdvisorAutoProxyCreator, 就可以对容器中的 bean 实现灵活的拦截
  
  
主题二 : 使用 Spring AOP

   spring 提供了多种不同的方案实现对 bean 的 aop proxy, 包括 ProxyFactoryBean, 便利的 TransactionProxyFactoryBean 以及 AutoProxyCreator 等,
   下图是 proxy class diagram 以供参考
  
  
   
   这里重点说一下最常用的 ProxyFactoryBean, TransactionProxyFactoryBean, BeanNameAutoProxyCreator, DefaultAdvisorAutoProxyCreator 的联系和区别
  
   1. ProxyFactoryBean : 使用率最高的 proxy 方式, 它通过配置 interceptorNames 属性决定加入哪些 advisor (method interceptor 将会被自动包装成 advisor, 下文将描述这个细节),
      注意是 "interceptorNames" 而不是 "interceptors", 原因是 ProxyFactoryBean 可能返回非 singleton 的 proxy 实例, 而 advisior 可能也是非 singleton 的, 因此不能通过 interceptor reference 来注入
     
   2. TransactionProxyFactoryBean : 特定用于 transaction proxy, 注意其 super class 是 AbstractSingletonProxyFactoryBean,  也就是说, TransactionProxyFactoryBean 永远无法返回非 singleton 的 proxy 实例 !!! 如果你需要非 singleton 的 proxy 实例, 请考虑使用 ProxyFactoryBean.
     
   3. BeanNameAutoProxyCreator : 故名思义, 根据 bean name 进行 auto proxy, bean name 的 match 规则参见 org.springframework.util.PatternMatchUtils
 
   4. DefaultAdvisorAutoProxyCreator : 更强大的 auto proxy creator, 强大之处在于它会 cahce 容器中所有注册的 advisor, 然后搜索容器中所有的 bean ,
      如果某个 bean 满足 advisor 中的 Pointcut, 那么将会被自动代理, 与 BeanNameAutoProxyCreator 相比, 省去了配置 beanNames 的工作,
     
      eg :
   
     
      
	      <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" />
			  <bean id="defaultPointcutAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor" scope="prototype">
			  		<property name="pointcut" ref="fooPointcut"/>
			  		<property name="advice" ref="fooAdvice"/>
				</bean>	
				
				<bean id="fooAdvice" class="com.mycompany.FooAdvice" scope="prototype" />
			
				<bean id="fooPointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut" scope="prototype">
			  		<property name="patterns">
			  			<list>
			  				<value>com.mycompany.FooService.*</value>
			  			</list>
			  		</property>
			  	</bean>
      

     
      以上配置将自动代理容器中所有 com.mycompany.FooService 类型的 bean, 并拦截其所有方法
     
     

深度话题
     
      1. MethodInterceptor 如何被包装成 Advisor ?
        
         在 AdvisorAdapterRegistry#wrap(Object) 方法中实现, code as below
        
        
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
  if (adviceObject instanceof Advisor) {
    return (Advisor) adviceObject;
  }
  if (!(adviceObject instanceof Advice)) {
    hrow new UnknownAdviceTypeException(adviceObject);
  }
  Advice advice = (Advice) adviceObject;
  if (advice instanceof MethodInterceptor) {
   // So well-known it doesn't even need an adapter.
   return new DefaultPointcutAdvisor(advice);
  }
  for (int i = 0; i < this.adapters.size(); i++) {
   / Check that it is supported.
							   AdvisorAdapter adapter = (AdvisorAdapter) this.adapters.get(i);
if (adapter.supportsAdvice(advice)) {
								 return new DefaultPointcutAdvisor(advice);
 }
}
  throw new UnknownAdviceTypeException(advice);
					}
         

        
         从代码可以看到, 如果 adviceObject(也就是 interceptorNames 对应的 bean) 不是 advisor
         而是 MethodInterceptor 或 Advice, 那么 spring 将其包装成 DefaultPointcutAdvisor,
         而 DefaultPointcutAdvisor 中定义的 Pointcut 是 TruePointcut :
        
        
         class TruePointcut implements Pointcut, Serializable {
	
						public static final TruePointcut INSTANCE = new TruePointcut();
						
						/**
						 * Enforce Singleton pattern.
						 */
						private TruePointcut() {
						}
					
						public ClassFilter getClassFilter() {
							return ClassFilter.TRUE;
						}
					
						public MethodMatcher getMethodMatcher() {
							return MethodMatcher.TRUE;
						}
						
						/**
						 * Required to support serialization. Replaces with canonical
						 * instance on deserialization, protecting Singleton pattern.
						 * Alternative to overriding <code>equals()</code>.
						 */
						private Object readResolve() {
							return INSTANCE;
						}
					
						public String toString() {
							return "Pointcut.TRUE";
						}
					
					}
         
         

        
         也就是说, MethodInterceptor 和 Advice 被包装成的 Advisor 将会匹配容器中的所有 bean,
所以, 永远不要在 DefaultAdvisorAutoProxyCreator 的 interceptorNames 中引用一个 Advice, 那将会使容器中所有的 bean 被自动代理!!! 此时应该考虑使用 BeanNameAutoProxyCreator 或者将 Advice 用特定的 Pointcut 包装成 advisor 后注入 DefaultAdvisorAutoProxyCreator.
     
      2. spring 中 interceptor 的执行顺序 ? TODO
      3. 一个 bean 可以被多次 proxy 吗 ?  TODO
  • 大小: 76.7 KB
  • 大小: 51.9 KB
分享到:
评论

相关推荐

    Spring AOP中文教程

    #### 一、AOP概览 面向切面编程(Aspect-Oriented Programming,简称AOP)是一种编程范式,它允许开发者将横切关注点(cross-cutting concerns)从业务逻辑中分离出来。横切关注点是指那些对应用程序多个部分都产生...

    spring AOP配置的几种方式

    #### 一、Spring AOP配置概览 面向切面编程(Aspect-Oriented Programming,简称AOP)是Spring框架的重要特性之一,它通过将业务逻辑中的横切关注点(Cross-cutting Concerns)与核心业务逻辑分离来提高代码的可...

    spring-aop.pdf 源码电子书

    标题和描述中提到的是关于Spring AOP源码的电子书。Spring AOP(Aspect-Oriented Programming)是Spring框架的一个重要组成部分,它支持面向切面编程的实践,是为了解决面向对象编程中的横切关注点问题而设计的。在...

    Spring 应用之AOP

    #### 一、AOP概览 AOP(Aspect-Oriented Programming,面向切面编程)是一种编程范式,旨在通过将横切关注点(cross-cutting concerns)从业务逻辑中分离出来,提高系统的模块化程度。在Spring框架中,AOP作为一种...

    Spring - 3 AOP

    #### 一、Spring框架概览 Spring 是一款轻量级的开源框架,主要用于简化企业级应用的开发工作。它提供了丰富的功能集,包括依赖注入(Dependency Injection, DI)、面向切面编程(Aspect-Oriented Programming, AOP...

    AOP面向切面编程总结

    #### 一、AOP概览 AOP(Aspect-Oriented Programming,面向切面编程)是一种编程思想和技术,它作为OOP(面向对象编程)的一种补充,主要解决了OOP在处理横切关注点方面的不足。在传统的面向对象程序设计中,通常会...

    SPRING技术内幕+深入解析SPRING架构与设计 55M(下载地址)

    4. **面向切面编程(AOP)与Spring AOP**: - 面向切面编程的基本概念及其在Spring中的应用。 - Spring AOP的实现原理,包括代理模式的选择(JDK动态代理、CGLIB)。 - 使用AspectJ进行切面编程的具体实践。 5. ...

    Spring技术内幕-深入解析_Spring架构与设计原理

    《Spring技术内幕-深入解析_Spring架构与设计原理》是一本深入探讨Spring框架核心机制与设计理念的专业书籍,由资深软件开发专家计文柯撰写。本书不仅适合Java开发者、Spring框架使用者,也对平台开发人员、系统架构...

    Spring技术内幕:深入解析Spring架构与设计原理(第2版)

    首先,书中会对Spring框架的整体架构进行概览,介绍Spring框架的各个模块,包括核心容器、数据访问/集成、Web模块、AOP(面向切面编程)、strumentation以及消息模块等。Spring框架的核心是控制反转(IoC)和面向切...

    Spring5.2.6源码解析

    一、Spring 核心组件概览 Spring 的核心组件包括: Spring Core: 提供基础设施,如 IoC 容器、BeanFactory 等。 Spring Context: 提供框架上下文信息的访问方式。 Spring AOP: 支持面向切面编程。 Spring DAO: 提供...

    Spring内容讲解与介绍

    ### Spring框架核心知识点详解 #### 一、Spring框架概述 ...以上是Spring框架的核心知识点概览,这些知识点涵盖了Spring框架的基本原理、核心技术以及使用指南等内容,对于初学者和开发者来说都是重要的学习资料。

    spring jar 包详解

    #### 一、Spring Jar 包概览 Spring 是一个开源的 Java 开发框架,主要用于简化企业级应用的开发工作。它通过提供一系列的基础框架,使得开发者能够更容易地处理复杂的业务逻辑,并且提高了代码的可维护性和可测试...

    Spring5.1中文参考指南.pdf

    - **Spring AOP的能力和目标**:Spring AOP的特点及其应用场景。 - **AOP代理**:Spring AOP的实现机制。 - **@AspectJ支持**:Spring对AspectJ的集成。 - **基于Schema的AOP支持**:使用XML配置AOP。 - **选择...

    Spring Framework 6 中文文档

    文档首先介绍了版权信息,随后详细阐述了Spring Framework的概览。"Spring"的理解不仅仅是框架本身,它代表了一个完整的生态系统,包括Spring Boot、Spring Cloud等。Spring的历史可以从其诞生背景和演进过程来理解...

    spring3 源码 项目

    以上就是Spring3主要模块的概览,每个模块都有其独特的功能,共同构建了Spring的强大生态系统。通过研究这些源码,开发者不仅可以了解Spring的工作原理,还可以借鉴其设计思想,提升自己的编程技巧和框架设计能力。

    springspring详细教程下载

    ### Spring框架概览 Spring框架是Java开发领域中的一个关键组成部分,尤其在企业级应用开发中占据着核心地位。它提供了全面的轻量级解决方案,涵盖了依赖注入(Dependency Injection,简称DI或IOC)、面向切面编程...

    Spring-Reference_zh_CN(Spring中文参考手册)

    12.5.1. iBATIS 1.x和2.x的概览与区别 12.5.2. iBATIS SQL Maps 1.x 12.5.2.1. 创建SqlMap 12.5.2.2. 使用 SqlMapTemplate 和 SqlMapDaoSupport 12.5.3. iBATIS SQL Maps 2.x 12.5.3.1. 创建SqlMapClient 12.5.3.2....

    Struts2,Spring与Hibernate整合应用,学生成绩管理系统

    ### Struts2、Spring与Hibernate整合应用:学生成绩管理系统 #### 一、知识点概览 本项目聚焦于Struts2、Spring与Hibernate三大框架的整合应用,旨在构建一个高效、稳定、易于维护的学生成绩管理系统。通过整合这...

    Pro Spring3

    - **XML 配置**:深入讨论使用 XML 进行 Spring 配置的方法和技术细节。 - **注解配置**:讲解使用注解进行配置的优势及应用场景。 - **混合配置**:探索同时使用 XML 和注解配置的可能性及最佳实践。 #### 六、...

Global site tag (gtag.js) - Google Analytics