:: 首页 ::  :: 联系 :: 聚合  :: 管理

Spring技术手册笔记(二):Spring AOP

Posted on 2009-11-08 20:12 codingliyi 阅读(596) 评论(0)  编辑  收藏 所属分类: Java EE

四、SpringAOP

学习AOP必须首先要学习代理模式。详见我的上一篇笔记:AOP基础:动态代理

AOP观念与术语

1.横切关注点(Cross-cutting concern

类似于日志记录、安全检查、事务等系统层面的服务,在一些应用程序中常被尖刀安插至各个对象的处理流程中,这些动作在AOP术语中被称为横切关注点。

2.切面(Aspect

将散落于各个业务对象中的横切关注点(如日志记录)收集起来,设计各个独立可重用的对象,这些对象被称为切面。如上篇笔记中的Handler类。在需要该服务时,织入(Weave)应用程序之上。

3.Advice

Aspect的具体实现被称之为Advice。例如,Advice中会包括日志记录程序代码是如何实现的。Advice中包含了横切关注点的行为或提供的服务。

4.Joinpoint

Aspect在应用程序执行时加入业务流程的点或时机。这个时机可能是某个方法执行之前或之后或两者都有,或是某个异常发生的时候。

5.Pointcut

Pointcut是一个定义,可在某个定义文件中编写Pointcut,指定某个Aspect在哪些Joinpoint时被织入。

Spring AOP

SpringAdvice是在执行时期导入至Targets的,可以让Target实现预先定义的接口,则Spring在执行时会使用动态代理;如不实现接口,则会使用CGLIBTarget产生一个子类作为代理类。

Spring只支持方法的Joinpoints,即Advices将在方法执行的前后调用。

Advices

Advices包括Aspect的真正逻辑,具体说来就是一个类,由于织入至Targets的时机不同,Spring提供了几种不同的Advices,如BeforeAdviceAfterAdviceArountAdviceThrowAdvice

BeforeAdvice

通过实现org.springframework.aop.MethodBeforeAdvice接口来实现逻辑。

该接口定义如下方法:

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

throws Throwable;

Before()方法声明为void,所以不用回传任何结果,在before()执行完毕之后,除非抛出异常,否则目标对象上的方法就会被执行。

示例代码如下:

1public class LogBeforeAdvice implements MethodBeforeAdvice {
2    Logger logger = Logger.getLogger(this.getClass().getName());
3    public void before(Method method, Object[] args, Object target)
4            throws Throwable {
5        logger.log(Level.INFO,"Method starts");
6    }

7}
在配置文件中写入以下内容:
 1<bean id="logBeforeAdvice" class="SpringAOP.LogBeforeAdvice"></bean>
 2
 3<bean id="helloSpeakerProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
 4    <!-- 如果下一行代码去掉,Spring将会使用CGLIB创建一个代理类 -->
 5    <property name="proxyInterfaces" value="SpringAOP.IHello"></property>
 6    <property name="target" ref="helloSpeaker"></property>
 7    <property name="interceptorNames">
 8        <list>
 9            <value>logBeforeAdvice</value>
10        </list>
11    </property>
12</bean>

AfterAdvice

通过实现org.springframework.aop.AfterReturningAdvice接口来实现。

该接口定义如下方法:

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

示例代码类似于BeforeAdvice

AroundAdvice

通过实现org.aopalliance.intercept.MethodIntercept接口来实现。

该接口定义如下方法:

public Object invoke(MethodInvocation methodInvocation) throws Throwable;

示例代码如下:

 1import org.aopalliance.intercept.MethodInterceptor;
 2import org.aopalliance.intercept.MethodInvocation;
 3
 4public class LogAroundAdvice implements MethodInterceptor {
 5    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
 6        System.out.println("AroundAdvice Begin");
 7        Object result = methodInvocation.proceed();
 8        System.out.println("AroundAdvice Finish");
 9        return result;
10    }

11}
配置文件类似于BeforeAdvice。

ThrowAdvice

通过实现org.springframework.aop.ThrowAdvice接口来实现。

该接口只是个标签接口,没有任何方法。可以定义任意方法名称,只要是如下形式:

methodName([Method], [args], [target], subclassOfThrowable);

其中[]表示可选。subclassOfThrowable必须是Throwable的子类。当异常发生时,会检验所设定的Throw Advice中是否有符合异常类型的方法,如有则执行。

注意:当异常发生时,ThrowAdvice的任务只是执行对应的方法,并不能处理异常。当其执行完毕后,原来的异常仍被传播至应用程序之中。

PointcutAdvisor

Spring中,可以指定更精细的织入时机,Pointcut定义了Advice的应用时机,在Spring中,使用PointcutAdvisorPointcutAdvice结合成一个对象。Spring内建的Pointcut都有对应的PointcutAdvisor

1Public interface Advisor{
2boolean isPerInstance();
3Advice getAdvice();
4}

5Public interface PointcutAdvisor extends Advisor{
6Pointcut getPointcut()
7}

NameMatchMethodPointcutAdvisor

这是最基本的PointcutAdvisor。可以指定所要应用的目标上的方法名称。

示例代码:

 1<bean id="helloPointcutAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
 2    <property name="mappedName">
 3        <value>say*</value>
 4    </property>
 5    <property name="advice">
 6        <ref bean="logAroundAdvice"/>
 7    </property>
 8</bean>
 9
10<bean id="helloSpeakerProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
11    <!-- 如果下一行代码去掉,Spring将会使用CGLIB创建一个代理类 -->
12    <property name="proxyInterfaces" value="SpringAOP.IHello"></property>
13    <property name="target" ref="helloSpeaker"></property>
14    <property name="interceptorNames">
15        <list>
16            <!-- 
17            <value>logBeforeAdvice</value>
18            <value>logAfterAdvice</value>
19            <value>logAroundAdvice</value>
20             -->
21            <value>helloPointcutAdvisor</value>
22        </list>
23    </property>
24</bean>

Autoproxy

自动代理可以不用为每一个目标对象手动定义代理对象,使用自动代理,可以透过Bean名称或是Pointcut的比对,自动为符合比对条件的目标对象建立代理对象。

BeanNameAutoProxyCreator

当应用程序很大时,可以为目标对象取好适当的Bean名称,例如xxxService。此时可修改Bean定义文件如下:

 1<bean id="proxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
 2    <property name="beanNames">
 3        <list>
 4            <value>*Speaker</value>
 5        </list>
 6    </property>
 7    <property name="interceptorNames">
 8        <list>
 9            <value>logAroundAdvice</value>
10        </list>
11    </property>
12</bean>

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


网站导航:
博客园   IT新闻   Chat2DB   C++博客   博问