疯狂

STANDING ON THE SHOULDERS OF GIANTS
posts - 481, comments - 486, trackbacks - 0, articles - 1
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

spring aop

Posted on 2010-09-07 22:03 疯狂 阅读(1908) 评论(0)  编辑  收藏 所属分类: java spring

AOP的术语

z

切面(aspect)

        切面是你要实现的交叉功能。就是通知和切入点的结合。通知和切入点共同定义了关于切面的全部内容:它的功能、在何时和何地完成功能。

通知(Advice)

      通知定义了切面是什么以及何时使用。除了描述切面要完成的工作,通知还解决了何时执行这个工作的问题。应该在一个方法被调用之前?之后?或者抛出异常时。

切入点(pointcut)
        如果说通知定义了切面的"什么"和"何时",那么切入点就定义了"何地"。


连接点(joinpoint)

      连接点是应用程序执行过程中能够插入切面的地点。这些点可以是方法被调用时、异常抛出时、甚至字段被编辑时。

引入(Intrduction)

        引入允许你为已经存在的类添加新方法和属性。比如一个Auditable通知类,记录对象在最后一次被修改时的状态。只需要一个setLastModified(Date)方法,和一个实例变量来保存这个状态。这个新方法和实例变量就可以被引入到现有的类,从而在不修改它们的情况下,让他们具有新的行为和状态。

目标对象(Target)

        目标对象是被通知的对象。

代理(Proxy)

         代理是将通知应用到目标对后创建的对象。

织入(weaving)

          织入是将切面应用到目标对象从而创建一个新的代理对象的过程。 在目标对象的生命周期里有多个机会发生织入过程。比如编译时、类加载时、运行时。


 

通知、切点、通知者

通知

在Spring AOP里有5中类型的通知,分别由一个接口进行定义

Before(前)

org.springframework.aop.MethodBeforeAdvice

After-returning(返回后)

org.springframework.aop.AfterReturningAdvice

After-throwing(抛出后)

org.springframework.aop.ThrowsAdvice

Around(周围)

org.aopalliance.intercept.MethodInterceptor

Introduction(引入)

org.springframework.aop.IntroductionInterceptor


<bean id="audienceAdvice" class="com.springidol.AudienceAdvice"></bean>

//AudienceAdvice类实现了3中不同的3中不同类型的AOP通知。

Public class AudienceAdvice implements MethodBeforeAdvice,AfterReturningAdvice,ThrowsAdvice{

//前通知要求实现的方法

public void before(Method method,Object[] args,Object target) throws Throwable{


}


//返回后通知要求实现的方法,Object returnValue表示被调用方法的返回值

public void  afterReturning(Object returnValue,Method method,Object[] args,Object target) throws Throwable{


}


//抛出后通知不需要实现任何方法,它只是一个标记接口,告诉spring相应的通知要求处理被抛出的异常,除最后一个参数外,其他参数都是可选的

public void afterThrowing(Method method,Object[] args,Object target,NullPointerException e) throws Throwable{


//当发生NullPointerException 时,记录日志

LOGGER.error("NPE thrown from "+method.getName());

}


}


其中的Method method参数,表示要使用这个通知的方法,第二个参数Object[] args是方法被调用时要传递的参数。最后一个是方法调用的目标也就是被调用方法所在的对象。

//周围通知相当于前通知、后通知、抛出后通知的结合。

Public class AudienceAdvice implements MethodInterceptor{

Public Object invoke(MethodInvocation invocation) throws Throwable{

try{

..............................    //在方法调用之前

Object returnValue=invocation.proceed();    调用目标方法

.............................    //在方法调用之后

}catch(PerformanceException e){

.............................    /在出现异常之后

}

}

}


切点

1.正则切点


切点的作用主要在于选择需要使用通知的方法,比如下面的正则表达式切点:

<bean id="performancePointcut"                      class="org.springframework.aop.support.JbkRegexpMethodPointcut">

<property name="pattern" value=".*perform" />

</bean>


Pattern属性用于制定方法匹配所使用的切点模板,本例中被设置为一个正则表达式,它应该匹配任何类里名为perform的方法。


定义切点后,把切点与通知关联


<bean id="audienceAdvisor"                     class="org.springframework.aop.support.DefaultPointcutAdvisor">

<property name="advice" value="audienceAdvice" />

<property name="pointcut" value="performancePointcut" />

</bean>


DefaultPointcutAdvisor是一个通知者类,它只是把通知关联到一个切点


也可以使用RegexpMethodPointcutAdvisor是一个特殊的通知者类,可以在一个Bean里面定义切点和通知者

<bean id="audienceAdvisor"                     class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">

<property name="advice" value="audienceAdvice" />

<property name="pattern" value=".*perform" />

</bean>


2.定义AspectJ切点


正则表达式虽然可以作为切点定义语言来使用,但是它并不是针对切点而创建的,其主要用途还是文本解析。AspectJ里定义切点的方法就可以看出AspectJ的切点语言是一种真正的切点表达式语言。


<bean id="performancePointcut"                     class="org.springframework.aop.aspectj.AspectJExpressionPointcut">

<property name="expression" value="execution(* Performer+.perform(..))" />

</bean>


可以使用DefaultPointcutAdvisor把它和通知关联起来,就像前面一样。同样,也可以设置一个特殊的通知者

<bean id="audienceAdvisor"                     class="org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor">

<property name="advice" value="audienceAdvice" />

<property name="expression" value="execution(* *.perform(..))" />

</bean>

execution* *.perform(..)) 

execution表示执行方法时,* *表示任意返回类型,.perform表示perform方法,(..)表示任意参数设置


使用ProxyFactoryBean


<bean id="duke"

          class="org.springframework.aop.framework.ProxyFactoryBean">

<property name="proxyInterfaces">

            <value>genericdaotest.dao.PersonDao</value>

        </property>

        <property name="target">

            <bean parent="abstractDaoTarget">

                <constructor-arg>

                    <value>genericdaotest.domain.Person</value>

                </constructor-arg>

            </bean>

        </property>

         <property name="interceptorNames">

             <list>

                 <value>audienceAdvisor</value>

             </list>

         </property>

  </bean>


Spring里面的ProxyFactoryBean是个工厂Bean,用于生成一个代理,把一个或者多个拦截者(和通知者)应用到Bean,有target、interceptorNames、proxyInterfaces三个属性,后两个都是数组属性target表示要代理的对象

interceptorNames属性告诉ProxyFactoryBean哪个通知者要应用于被代理的

beanproxyInterfaces告诉ProxyFactoryBean代理应该实现哪个接口。本例中代理的是genericdaotest.dao.PersonDao接口

target告诉ProxyFactoryBean,哪个Bean是代理。



----------------以上转载自:http://bhsc.happy.blog.163.com/blog/static/1043895522008111144158773/



只有注册用户登录后才能发表评论。


网站导航: