posts - 66,  comments - 11,  trackbacks - 0
    Spring的AOP框架允许你将分散在系统中的功能块放到一个地方-切面。重用通用功能的常用面向对象技术是使用继承和委

托模式。但由于基础类在系统中到处使用,使用继承会引起脆弱的继承关系。委托模式比较笨拙,依然需要重复调用委托对象

。使用AOP,你也是在一个地方定义通用功能,只是你可以声明式定义何时何地应用这些功能,而不一年欧冠在需要新功能的地

方修改代码。交叉业务现在可以被模块化到特定对象切面中。这样做有2个好处,第一,现在每个业务逻辑放在一个地方,而不

是分散到代码的各个角落。第二,我们的服务模块现在更加清晰,因为他们只包含他们的核心功能,辅助功能转移到切面中。

    切面(Aspect):切面是你要实现的交叉功能。切面最常用的例子是日志记录。日志记录在系统中到处需要用到。
    连接点(Joinpoint):连接点是应用程序执行过程中插入切面的地点。这个地点可以是方法调用,异常抛出,或者是要修改

字段。切面代码在这些地方插入到你的应用流程中,添加新的行为。
    通知(Advice):通知切面的实际实现。它通知应用系统新的行为。
    切入点(PointCut):切入点定义了通知应该应用在哪些连接点。通知可以应用到AOP框架支持的任何连接点。你并不希望把

所有切面应用到所有可能的连接点上。切入点让你指定通知应用到什么地方。
    引入(Introduction):引入允许你为已存在类添加新方法和属性。
    目标对象(Target):目标对象是被通知对象。它既可以是你编写的类也可以是你要添加定制行为的第三方类。
    代理(Proxy):代理是将通知应用到目标对象后创建的对象。对于客户对象来说,目标对象和代理对象是一样的。
    织入(Weaving):织入是将切面应用到目标对象从而创建一个新的代理对象的过程。
    切入点定义了哪些连接点要被通知。

    Spring的AOP实现:
    在Spring中所有的通知都以Java类的形式编写。代理Bean只有在第一次被应用系统需要的时候才被创建。如果你使用的是ApplicationContext,代理对象在BeanFactory载入所有Bean的时候被创建。因为Spring在运行期创建代理,所以使用Spring AOP不需要特殊编译期。
    Spring有2种代理创建方式。如果目标对象实现了一个接口暴露的方法,Spring将使用JDK的Java.lang.reflect.Proxy类创建代理。这个类让Spring动态产生一个新的类,它实现了所需的接口,织入了通知,并且代理对目标对象的所有请求。
    如果目标对象没有实现任何接口,Spring使用CGLIB库生成目标对象的子类。在创建这个子类的时候,Spring将通知织入,并且对目标对象的调用委托给这个子类。

    通知包含了切面的逻辑。所以当你创建一个通知对象的时候,你是在编写实现交叉功能的代码。而且,记住Spring的连接点模型是建立在方法拦截上。这意味着你编写的Spring通知会在方法调用周围的各个地方织入系统中。通知的类型有:Around,Before,After,Throws

前置通知:需要扩展MethodBeforeAdvice接口
public interface MethodBeforeAdvice{
    void before(Method method,Object[] args,Object target)throws Throwable;
}

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
    
<!-- 创建代理目标对象 -->
    
<bean id="kwikEMartTarget" class="com.springinaction.chapter03.store.ApuKwikEMart"></bean>
    
<!-- 创建通知 -->
    
<bean id="welcomeAdvice" class="com.springinaction.chapter03.store.WelcomeAdvice"></bean>
    
<!-- 创建代理对象 -->
    
<bean id="kwikEMart" class="org.springframework.aop.framework.ProxyFactoryBean">
        
<!-- 代理类实现的接口 -->
        
<property name="proxyInterfaces">
            
<value>com.springinaction.chaper03.store.kwikEMart</value>
        
</property>
        
<!-- 要织入的通知 -->
        
<property name="interceptorNames">
            
<list>
                
<value>welcomeAdvice</value>
            
</list>
        
</property>
        
<!-- 要代理的目标对象 -->
        
<property name="target">
            
<ref bean="kwikEMartTarget"/>
        
</property>
    
</bean>
</beans>

ProxyFactoryBean类是一个在BeanFactory中显示的创建代理对象的中心类。像我们展示的那样,你可以给它一个要实现的接口,一个要代理的目标对象,一个要织入的通知,并且它将创建一个崭新的代理对象。通常配置ProxyFactoryBean,让它实现和目标对象一样的接口。

后置通知:需要实现AfterReturningAdvice
public interface AfterReturningAdvice{
    void afterReturning(Object returnValue,Method method,Object[] args,Object target)throws Throwable;
}

环绕通知:需要实现MethodInterceptor,同时实现前置和后置通知
public interface MethodInterceptor extends Interceptor{
    Object invoke(MethodInvocation invocation)throws Throwable;
}
MethodInterceptor接口和前面介绍的2种通知不同点:
1、MethodInterceptor能够控制目标方法是否真的被调用。通过调用MethodInvocation.proceed()方法来调用目标方法。这一点不同于前两个,目标方法总是被调用的。
2、MethodInterceptor让你可以控制返回的对象。就是说你可以返回一个与proceed()方法返回对象完全不同的对象。
package com.wyq.spring.base.aopinstance;

import java.util.HashSet;
import java.util.Set;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.jboss.remoting.samples.transporter.basic.Customer;


/** 
 * 
@author 作者 
 * 
@version 创建时间:2009-11-5 下午05:19:19 
 * 类说明 
 
*/
public class OnePerCustomerInterceptor implements MethodInterceptor {
    
//定义包含用户的集合
    private Set customers = new HashSet();
    
/*
     * 当你在方法调用的前后都需要交叉切面逻辑时,应该使用MethodInterceptor。由于你必须要记得显示调用
     * invocation.proceed()方法,所以,在满足要求的情况下,最好还是使用MethodBeforeAdvice或
     * AfterReturningAdvice.
     
*/
    
    
public Object invoke(MethodInvocation invocation) throws Throwable {
         Customer customer 
= (Customer)invocation.getArguments()[0];
         
if(customers.contains(customer)){
             System.out.println(
"抛出异常");
         }
         
//调用目标方法
         Object squishee = invocation.proceed();
         
//添加用户
         customers.add(customer);
         
//返回目标方法结果
        return squishee;
    }
}



   
posted on 2009-11-05 17:31 王永庆 阅读(208) 评论(0)  编辑  收藏 所属分类: SPRING

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


网站导航:
 
<2009年11月>
25262728293031
1234567
891011121314
15161718192021
22232425262728
293012345

常用链接

留言簿(1)

随笔分类

随笔档案

关注blogs

搜索

  •  

最新评论

阅读排行榜

评论排行榜