spring aop小结

 
spring aop 小结
总结前几天的项目实践,对spring aop的使用做个小结。
首先要理解的是AOP的概念 顾名思义,面向切面编程( AOP )是以识别和创建 切面 为基础 的编程。说它们是横切,是因为它们总是切入模块(如包、类和代码文件)的多个单位。
其次,要掌握spring aop的几个基本的概念。
切面(aspect):一个关注点的模块化,这个关注点可能会横切多个对象。
连接点(joinpoint):在程序的执行过程中某个特定的点,比如某方法调用的时候或者处理异常的时候。在 Spring AOP中,一个链接点总是代表一个方法的执行。
通知(advice):在切面的某个特定的链接点上执行的动作。通知有各种类型,其中包括“before”“after”“around”“throw”四种类型。
切入点(pointcut):匹配链接点的断言。通知和一个切入点表达式关联,并在满足这个切入点的链接点上运行。
织入(weave):把切面连接到其它的应用程序类型或者对象上,并创建一个被通知的对象。Spring在运行时完成织入。
在spring 2.0中声明切面、通知等有两种方式:一种是配置xml文件的方式,一种是基于@AspectJ方式的,即annotation方式的。但是这种注解方式只适用于Java 5的版本,如果是Java 5以下版本,只能使用传统的xml方式。
u      声明一个切面:
       切面使用<aop:aspect>来声明,支持bean通过ref属性来引用:
<aop:config>
       <aop:aspect id=”myAspect” ref=”aBean”>
              ...
       </aop:aspect>
</aop:config>
<bean id=”aBean” class=”…”>
       …
</bean>
       切面的支持bean(上列中的”aBean”)可以象其他Spring bean一样被容器管理配置以及依赖注入。
u      切入点声明:
       切入点可以在切面里面声明,这种情况下切入点只在切面内部可见。切入点可以直接在<aop:config>下定义,这样就可以使多个切面和通知容器共享该切入点。
<aop:config>
       <aop:pointcut id=”businessService”expression=”execution(* com.xyz.myapp.service.*.*(..))” />
</aop:config>
在这里expression表达式是一个正则表达式,它的一般的规则为:
execution(modifiers-pattern ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)
其中带问号的modifiers-pattern?(public/protected) 和 declaring-type-pattern? throws-pattern??可以不填
可见execution(* *..BookManager.save(..))
* 第一颗* 代表ret-type-pattern 返回值可任意,
* *..BookManager 代表任意Pacakge里的BookManager类。
如果写成com.xyz.service.* 则代表com.xyz.service下的任意类
com.xyz.service..* com.xyz.service则代表com.xyz.service及其子package下的任意类
* save代表save方法,也可以写save* 代表saveBook()等方法
* (..) 匹配0个参数或者多个参数的,任意类型
(x,..) 第一个参数的类型必须是X?
(x,,,s,..) 匹配至少4个参数,第一个参数必须是x类型,第二个和第三个参数可以任意,第四个必须是s类型。
u      通知类型 (advice)
       有四种通知类型:
       Around 通知、前置通知、异常通知、后置通知。这几种通知分别继承与这几种接口:
       MethodInterceptor、 MethorBeforeAdvice 、ThrowsAdvice 、AfterReturningAdvice
前置通知(before advice):
Before 通知在匹配方法执行前进入。定义一个前置通知必须继承MethodBeforeAdvice接口,实现before方法。前置通知可以在连接点执行之前插入自定义行为,但是不能修改链接点的返回值。
After returning通知在匹配的方法完全执行后运行。它必须实现AfterReturningAdvice接口,并实现afterReturning方法。一个后置通知可以访问返回值,但是不能进行修改。被调用方法、方法参数以及目标对象。
After throwing通知在匹配方法抛出异常退出时执行。
Around通知在匹配方法运行期的“周围”执行。它有机会在目标方法的前面和后面执行,并决定什么时候运行,怎么运行,甚至是否运行。使用around通知必须实现MethodInterceptor接口,并实现其中的invoke(MethodInvocation invoction)方法。Invoction参数暴露了被调用的方法、目标链接点、AOP代理以及传递给方法的参数。Invoke()方法应该返回调用结果。
u      增强器 (advisors)
       “advisors”这个概念来自Spring 1.2对AOP的支持,在AspectJ中是没有等价的概念。Advisor就像一个小的自包含切面,这个切面只有一个通知。切面自身通过一个bean表示,并且必须实现一个通知接口。
       Spring 2.0通过<aop:advisor>元素来支持advisor概念。格式如下:
<aop:config >
       <aop:pointcut id=”businessService”
                     expression=”execution(* com.xyz.myapp.service.*.*(..))”/>
    <aop:advisor pointcut="businessService"
                     advice-ref="advice"/>
</aop:config>
<bean id =”advice” class=”com.xyz.**”/>
同时,我们还可以使用pointcut属性来定义一个内联的切入点表达式。
所以可以写成如下:
<aop:config >             
<aop:advisor 
expression=”execution(* com.xyz.myapp.service.*.*(..))”
                     advice-ref="advice"/>
</aop:config>
<bean id =”advice” class=”com.xyz.**”/>
 
 
       下面有一个实例,这是我在项目中的运用:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd"
       default-autowire="byName">
      
    <aop:config proxy-target-class="true">
        <aop:advisor pointcut="execution(* *..InsertRevertAction.execute())"
                     advice-ref="insertAdvice"/>
    </aop:config>
      
    <bean id="insertAdvice" class="org.fengzhong.comf.core.staticpage.aop.AfterInsertRvertAdvice">
             
    </bean>
 
</beans>
 
public class AfterInsertRvertAdvice implements AfterReturningAdvice{
    private StaticPageService staticPageService ;
   
    private LocalCache localCache ;
 
    public void setStaticPageService(StaticPageService staticPageService) {
       this . staticPageService = staticPageService;
    }
   
    public void setLocalCache(LocalCache localCache) {
       this . localCache = localCache;
    }
 
    public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {
       if (arg0.toString().equals( "success" )) {
          
           System. out .println( "AOP after advice: attribute is " + PropertyUtils.getProperty(arg3, "model" ));
           System. out .println( "AOP after advice: attribute is "
                  + PropertyUtils.getProperty(PropertyUtils.getProperty(arg3, "model" ), "noteId" ));
           //localCache.remove(arg0, arg1)
           String id = (String) PropertyUtils.getProperty(
                  PropertyUtils.getProperty(arg3, "model" ), "noteId" );
           staticPageService .updateFlagById(id);
       }
    }
 
Spring 的代理缺省使用j2se的动态代理来作为AOP的代理。这样任何接口都可以被代理。同时Spring也支持使用CGLIB代理。对于需要代理类而不是代理接口的时候CGLIB代理是很必要的。
使用spring2.0 和spring 1.*的最大的区别,就是xml文件标签的语法配置。Spring2.0开发组建议使用xml的schema方式,如上例所示:
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd"
       default-autowire="byName">
但是Spring 2.0中冶提供了基于DTD的设置方式:
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
建议使用第一种,因为有时候会出现无法加载文件的问题。 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值