【Spring学习】Spring的AOP模块应用详解

面向切面编程(AOP)的思想就是在执行某些代码前执行另外的代码,使程序更灵活、扩展性更好,可以随便地添加删除某些功能。

javaweb机制中的filter就是面向切面编程的例子。Tomcat会在程序运行的某个时机(即servlet执行前后),执行与servlet、JSP等毫无关系的filter代码。

AOP把一个业务流程分成几个部分,例如权限检查,业务处理,日志记录,每个部分单独处理,然后把它们组装成完整的业务流程。每个部分被称为切面(Aspect)或者关注点。Spring提供的AOP机制异常灵活,能够在任何类、任何方法的执行前、后添加拦截器。Spring推荐使用接口编程,Spring提供三种拦截器:方法前拦截器、返回后拦截器、异常抛出拦截器。

下面我们从一个简单的例子开始学习spring aop:

//Service接口  
public interface IAopService{  
    public void withAop() throws Exception;         //将会被拦截  
    public void withoutAop() throws Exception;      //不会被拦截  
}  

//Service接口 实现类
public class AopServiceImpl implements IAopService{  
    private String name;  
    public void withAop() throws Exception{  
        System.out.println("有AOP的函数运行。name:"+name);  
        if(name.trim().length() == 0){  
            throw new AccountException("name属性不能为空");  
        }  
    }  

    public void withoutAop() throws Exception{  
            System.out.println("没有AOP的函数运行。");  
    }  

    public void setName(String name){  
        this.name = name;  
    }  

    public String getName(){  
        return this.name;  
    }  
}  

方法前拦截器,检查name是否为空:

import  org.springframework.aop.MethodBeforeAdvice;  
public class MethodBeforeInterceptor implements MethodBeforeAdvice{  
    //调用对象的方法前执行该方法  
    //参数分别为被调用的方法、被调用方法的参数、对象  
    public void before(Method method,Object [] args,Object instance) throws Throwable{  
        System.out.println("即将执行方法:"+method.getName());  
        //  
        if(instance instanceof AopServiceImpl){  
            String name = ((AopServiceImpl)instance).getName();  
            if(name == null){  
                throw new NullPointerException("name不能为空");  
            }  
        }  
    }  

}  

返回后拦截器:

import  org.springframework.aop.AfterReturningAdvice;  
public class MethodAfterInteceptor implements AfterReturningAdvice{  
    //参数分别为方法返回值、被调用方法、方法参数、被拦截的对象  
    public void afterReturning(Object value,Method method,Object [] args,Object instance) throws Throwable{  
                System.out.println("方法:"+method.getName()+"执行完毕,返回值为:"+value);  
    }     
} 

异常拦截器捕获异常 :

import  org.springframework.aop.ThrowAdvice;  
public class ThrowsInterceptor implements ThrowAdvice{  
    //参数分别为被调用的方法、方法参数、对象实例、抛出的异常  
    //前三个参数可以省略,第四个参数是必须的,这样设计是为了使开发者灵活地定义多个方法捕获各种不同的异常  
    public void afterThrowing(Method method,Object [] args,Object instance,AccountException ex) throws Throwable {  
        System.out.println("方法:"+method.getName()+"抛出了异常:"+ex);  
    }  

    public void afterThrowing(NullPointerException ex) throws Throwable {  
        System.out.println("抛出了异常:"+ex);  
    }  

}

拦截器配置:
Spring无法将Service的实现类与拦截器直接组装,因为没有对应的setter、getter方法。安装时借助的是Spring的代理类,把拦截器安装到NameMatchMethodPointcutAdvisor中,把自动以的Service安装到ProxyFactoryBean中,然后组装到一块。

<!-- 方法前拦截器MethodBeforeInterceptor安装到NameMatchMethodPointcutAdvisor中 -->  
<bean id="aopMethodBeforeInterceptor" class="org.springframework.aop.support. NameMatchMethodPointcutAdvisor">  
    <!--  拦截器的实现类-->  
    <property name="advice">  
        <bean class="com.lmb.spring. MethodBeforeInterceptor">  
    </property>  
    <!--  欲拦截的方法名-->  
    <property name="mappedName" value="withAop">  </property>  
</bean>  

<!-- 类似的方式配置返回后前拦截器MethodAfterInteceptor -->  
<bean id="aopMethodAfterInterceptor" class="org.springframework.aop.support. NameMatchMethodPointcutAdvisor">  
    <property name="advice">  
        <bean class="com.lmb.spring. MethodAfterInteceptor">  
    </property>  
    <property name="mappedName" value="withAop">  </property>  
</bean>  

<!-- 类似的方式配置异常前拦截器MethodAfterInteceptor -->  
<bean id="aopThrowsInterceptor" class="org.springframework.aop.support. NameMatchMethodPointcutAdvisor">  
    <property name="advice">  
        <bean class="com.lmb.spring.ThrowsInterceptor">  
    </property>  
    <property name="mappedName" value="withoutAop">   </property>  
</bean>  

<!-- Service实现类,安装到ProxyFactoryBean -->  
<bean id="aopService" class="org.springframework.aop.ProxyFactoryBean">  
    <!-- 安装拦截器-->  
    <property name="interceptorNames">  
        <list>  
            <value>aopMethodBeforeInterceptor</value>  
            <value>aopMethodAfterInterceptor</value>  
            <value>aopThrowsInterceptor</value>  
        </list>  
    </property>  
    <!-- 被拦截的对象-->  
    <property name="target">  
        <bean class="com.lmb.spring.AopServiceImpl">  
            <property name="name" value="HelloSpring"></property>  
        </bean>  
    </property>  
</bean>  

切面Aspect:在本例中,方法withAop()、withoutAop()中都有一些代码,这些代码可以看做是AOP中的切面,可以将切面理解为模块;

通知Advisor:本例的三个拦截器都是实现自某个接口,从类名上看就知道三个拦截器都是AOP中的通知。一旦Spring符合条件,就会派发出通知,即一些需要执行的代码,能实现某种功能;

切入点Pointcut:在配置拦截器时,XML中只配置了withAop()方法使用拦截器,而withoutAop()方法没有配置拦截器,这种配置是借助于org.springframework.aop.support. NameMatchMethodPointcutAdvisor完成的。这就是一个切入点,配置时可以使用通配符。该类说明上也带有Advisor是因为它也是用通知实现的;

AOP的相关概念总结:

方面(Aspect):一个关注点的模块化,这个关注点实现可能另外横切多个对象。事务管理是J2EE应用中一个很好的横切关注点例子。方面用spring的 Advisor或拦截器实现。

连接点(Joinpoint): 程序执行过程中明确的点,如方法的调用或特定的异常被抛出。

通知(Advice): 在特定的连接点,AOP框架执行的动作。各种类型的通知包括“around”、“before”和“throws”通知。通知类型将在下面讨论。许多AOP框架包括Spring都是以拦截器做通知模型,维护一个“围绕”连接点的拦截器链。Spring中定义了四个advice: BeforeAdvice, AfterAdvice, ThrowAdvice和DynamicIntroductionAdvice。

切入点(Pointcut): 指定一个通知将被引发的一系列连接点的集合。AOP框架必须允许开发者指定切入点:例如,使用正则表达式。 Spring定义了Pointcut接口,用来组合MethodMatcher和ClassFilter,可以通过名字很清楚的理解, MethodMatcher是用来检查目标类的方法是否可以被应用此通知,而ClassFilter是用来检查Pointcut是否应该应用到目标类上。

引入(Introduction): 添加方法或字段到被通知的类。 Spring允许引入新的接口到任何被通知的对象。例如,你可以使用一个引入使任何对象实现 IsModified接口,来简化缓存。Spring中要使用Introduction, 可有通过DelegatingIntroductionInterceptor来实现通知,通过DefaultIntroductionAdvisor来配置Advice和代理类要实现的接口。

目标对象(Target Object): 包含连接点的对象。也被称作被通知或被代理对象。

AOP代理(AOP Proxy): AOP框架创建的对象,包含通知。 在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。

织入(Weaving): 组装方面来创建一个被通知对象。这可以在编译时完成(例如使用AspectJ编译器),也可以在运行时完成。Spring和其他纯Java AOP框架一样,在运行时完成织入。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值